Changeset View
Changeset View
Standalone View
Standalone View
source/gameengine/Ketsji/BL_Texture.cpp
| Context not available. | |||||
| * \ingroup ketsji | * \ingroup ketsji | ||||
| */ | */ | ||||
| #include "glew-mx.h" | |||||
| #include <iostream> | |||||
| #include <map> | |||||
| #include <stdlib.h> | |||||
| #include "BL_Material.h" | |||||
| #include "BL_Texture.h" | #include "BL_Texture.h" | ||||
| #include "MT_assert.h" | #include "KX_CubeMap.h" | ||||
| #include "DNA_texture_types.h" | #include "DNA_texture_types.h" | ||||
| #include "DNA_image_types.h" | |||||
| #include "IMB_imbuf_types.h" | |||||
| #include "BKE_image.h" | |||||
| #include "BLI_blenlib.h" | |||||
| #include "RAS_ICanvas.h" | |||||
| #include "RAS_Rect.h" | |||||
| #include "KX_GameObject.h" | #include "GPU_texture.h" | ||||
| #include "GPU_draw.h" | |||||
| #define spit(x) std::cout << x << std::endl; | #include "KX_PyMath.h" | ||||
| #include "MEM_guardedalloc.h" | #include "BLI_math.h" | ||||
| #include "GPU_draw.h" | |||||
| #include "GPU_extensions.h" | |||||
| extern "C" { | BL_Texture::BL_Texture(MTex *mtex) | ||||
| // envmaps | :CValue(), | ||||
| #include "IMB_imbuf.h" | m_isCubeMap(false), | ||||
| void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf); | m_mtex(mtex), | ||||
| void my_free_envmapdata(EnvMap *env); | m_gpuTex(NULL) | ||||
| { | |||||
| Tex *tex = m_mtex->tex; | |||||
| EnvMap *env = tex->env; | |||||
| m_isCubeMap = (env && tex->type == TEX_ENVMAP && (env->stype == ENV_LOAD || env->stype == ENV_REALT)); | |||||
| Image *ima = tex->ima; | |||||
| ImageUser& iuser = tex->iuser; | |||||
| const int gltextarget = m_isCubeMap ? GetCubeMapTextureType() : GetTexture2DType(); | |||||
| m_gpuTex = (ima ? GPU_texture_from_blender(ima, &iuser, gltextarget, false, 0.0, true) : NULL); | |||||
| // Initialize saved data. | |||||
| m_name = std::string(m_mtex->tex->id.name + 2); | |||||
| m_savedData.colintensfac = m_mtex->difffac; | |||||
| m_savedData.colfac = m_mtex->colfac; | |||||
| m_savedData.alphafac = m_mtex->alphafac; | |||||
| m_savedData.specintensfac = m_mtex->specfac; | |||||
| m_savedData.speccolorfac = m_mtex->colspecfac; | |||||
| m_savedData.hardnessfac = m_mtex->hardfac; | |||||
| m_savedData.emitfac = m_mtex->emitfac; | |||||
| m_savedData.mirrorfac = m_mtex->mirrfac; | |||||
| m_savedData.normalfac = m_mtex->norfac; | |||||
| m_savedData.parallaxbumpfac = m_mtex->parallaxbumpsc; | |||||
| m_savedData.parallaxstepfac = m_mtex->parallaxsteps; | |||||
| m_savedData.lodbias = m_mtex->lodbias; | |||||
| m_savedData.ior = m_mtex->ior; | |||||
| m_savedData.ratio = m_mtex->refrratio; | |||||
| m_savedData.uvrot = m_mtex->rot; | |||||
| copy_v3_v3(m_savedData.uvoffset, m_mtex->ofs); | |||||
| copy_v3_v3(m_savedData.uvsize, m_mtex->size); | |||||
| if (m_gpuTex) { | |||||
| m_bindCode = GPU_texture_opengl_bindcode(m_gpuTex); | |||||
| m_savedData.bindcode = m_bindCode; | |||||
| GPU_texture_ref(m_gpuTex); | |||||
| } | |||||
| } | } | ||||
| // (n&(n-1)) zeros the least significant bit of n | BL_Texture::~BL_Texture() | ||||
| static int is_power_of_2_i(int num) | |||||
| { | { | ||||
| return ((num)&(num-1))==0; | // Restore saved data. | ||||
| m_mtex->difffac = m_savedData.colintensfac; | |||||
| m_mtex->colfac = m_savedData.colfac; | |||||
| m_mtex->alphafac = m_savedData.alphafac; | |||||
| m_mtex->specfac = m_savedData.specintensfac; | |||||
| m_mtex->colspecfac = m_savedData.speccolorfac; | |||||
| m_mtex->hardfac = m_savedData.hardnessfac; | |||||
| m_mtex->emitfac = m_savedData.emitfac; | |||||
| m_mtex->mirrfac = m_savedData.mirrorfac; | |||||
| m_mtex->norfac = m_savedData.normalfac; | |||||
| m_mtex->parallaxbumpsc = m_savedData.parallaxbumpfac; | |||||
| m_mtex->parallaxsteps = m_savedData.parallaxstepfac; | |||||
| m_mtex->lodbias = m_savedData.lodbias; | |||||
| m_mtex->ior = m_savedData.ior; | |||||
| m_mtex->refrratio = m_savedData.ratio; | |||||
| m_mtex->rot = m_savedData.uvrot; | |||||
| copy_v3_v3(m_mtex->ofs, m_savedData.uvoffset); | |||||
| copy_v3_v3(m_mtex->size, m_savedData.uvsize); | |||||
| if (m_gpuTex) { | |||||
| GPU_texture_set_opengl_bindcode(m_gpuTex, m_savedData.bindcode); | |||||
| GPU_texture_free(m_gpuTex); | |||||
| } | |||||
| } | } | ||||
| static int power_of_2_min_i(int num) | |||||
| void BL_Texture::CheckValidTexture() | |||||
| { | { | ||||
| while (!is_power_of_2_i(num)) | if (!m_gpuTex) { | ||||
| num= num&(num-1); | return; | ||||
| return num; | } | ||||
| /* Test if the gpu texture is the same in the image which own it, if it's not | |||||
| * the case then it means that no materials use it anymore and that we have to | |||||
| * get a pointer of the updated gpu texture used by materials. | |||||
| * The gpu texture in the image can be NULL or an already different loaded | |||||
| * gpu texture. In both cases we call GPU_texture_from_blender. | |||||
| */ | |||||
| int target = m_isCubeMap ? TEXTARGET_TEXTURE_CUBE_MAP : TEXTARGET_TEXTURE_2D; | |||||
| if (m_gpuTex != m_mtex->tex->ima->gputexture[target]) { | |||||
| Tex *tex = m_mtex->tex; | |||||
| Image *ima = tex->ima; | |||||
| ImageUser& iuser = tex->iuser; | |||||
| const int gltextarget = m_isCubeMap ? GetCubeMapTextureType() : GetTexture2DType(); | |||||
| // Restore gpu texture original bind cdoe to make sure we will delete the right opengl texture. | |||||
| GPU_texture_set_opengl_bindcode(m_gpuTex, m_savedData.bindcode); | |||||
| GPU_texture_free(m_gpuTex); | |||||
| m_gpuTex = (ima ? GPU_texture_from_blender(ima, &iuser, gltextarget, false, 0.0, true) : NULL); | |||||
| if (m_gpuTex) { | |||||
| int bindCode = GPU_texture_opengl_bindcode(m_gpuTex); | |||||
| // If our bind code was the same as the previous gpu texture bind code, then we update it to the new bind code. | |||||
| if (m_bindCode == m_savedData.bindcode) { | |||||
| m_bindCode = bindCode; | |||||
| } | |||||
| m_savedData.bindcode = bindCode; | |||||
| GPU_texture_ref(m_gpuTex); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| // Place holder for a full texture manager | bool BL_Texture::Ok() const | ||||
| class BL_TextureObject | |||||
| { | { | ||||
| public: | return (m_gpuTex != NULL); | ||||
| unsigned int gl_texture; | } | ||||
| void* ref_buffer; | |||||
| }; | |||||
| typedef std::map<char*, BL_TextureObject> BL_TextureMap; | bool BL_Texture::IsCubeMap() const | ||||
| static BL_TextureMap g_textureManager; | { | ||||
| static GLint g_max_units = -1; | return m_isCubeMap; | ||||
| } | |||||
| MTex *BL_Texture::GetMTex() const | |||||
| { | |||||
| return m_mtex; | |||||
| } | |||||
| BL_Texture::BL_Texture() | Tex *BL_Texture::GetTex() const | ||||
| : mTexture(0), | |||||
| mOk(0), | |||||
| mNeedsDeleted(0), | |||||
| mType(0), | |||||
| mUnit(0), | |||||
| mEnvState(0) | |||||
| { | { | ||||
| // -- | return m_mtex->tex; | ||||
| } | } | ||||
| BL_Texture::~BL_Texture() | Image *BL_Texture::GetImage() const | ||||
| { | { | ||||
| // -- | return m_mtex->tex->ima; | ||||
| } | } | ||||
| void BL_Texture::DeleteTex() | GPUTexture *BL_Texture::GetGPUTexture() const | ||||
| { | { | ||||
| if ( mNeedsDeleted ) { | return m_gpuTex; | ||||
| glDeleteTextures(1, (GLuint*)&mTexture); | } | ||||
| mNeedsDeleted = 0; | |||||
| mOk = 0; | |||||
| } | |||||
| if (mEnvState) { | unsigned int BL_Texture::GetTextureType() | ||||
| glDeleteLists((GLuint)mEnvState, 1); | { | ||||
| mEnvState =0; | return GPU_texture_target(m_gpuTex); | ||||
| } | } | ||||
| if (mDisableState) { | void BL_Texture::ActivateTexture(int unit) | ||||
| glDeleteLists((GLuint)mDisableState, 1); | { | ||||
| mDisableState =0; | /* Since GPUTexture can be shared between material textures (MTex), | ||||
| } | * we should reapply the bindcode in case of VideoTexture owned texture. | ||||
| g_textureManager.clear(); | * Without that every material that use this GPUTexture will then use | ||||
| * the VideoTexture texture, it's not wanted. */ | |||||
| GPU_texture_set_opengl_bindcode(m_gpuTex, m_bindCode); | |||||
| GPU_texture_bind(m_gpuTex, unit); | |||||
| } | } | ||||
| void BL_Texture::DisableTexture() | |||||
| { | |||||
| GPU_texture_unbind(m_gpuTex); | |||||
| } | |||||
| bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) | unsigned int BL_Texture::swapTexture(unsigned int bindcode) | ||||
| { | { | ||||
| // swap texture codes | |||||
| unsigned int tmp = m_bindCode; | |||||
| m_bindCode = bindcode; | |||||
| // return original texture code | |||||
| return tmp; | |||||
| } | |||||
| ImBuf *ibuf; | // stuff for cvalue related things | ||||
| if (!img || img->ok==0) | std::string BL_Texture::GetName() | ||||
| { | { | ||||
| mOk = false; | return RAS_Texture::GetName(); | ||||
| return mOk; | } | ||||
| } | |||||
| ibuf= BKE_image_acquire_ibuf(img, NULL, NULL); | #ifdef WITH_PYTHON | ||||
| if (ibuf==NULL) | |||||
| { | PyTypeObject BL_Texture::Type = { | ||||
| img->ok = 0; | PyVarObject_HEAD_INIT(NULL, 0) | ||||
| mOk = false; | "BL_Texture", | ||||
| return mOk; | sizeof(PyObjectPlus_Proxy), | ||||
| } | 0, | ||||
| py_base_dealloc, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| 0, | |||||
| py_base_repr, | |||||
| 0, 0, 0, 0, 0, 0, 0, 0, 0, | |||||
| Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, | |||||
| 0, 0, 0, 0, 0, 0, 0, | |||||
| Methods, | |||||
| 0, | |||||
| 0, | |||||
| &CValue::Type, | |||||
| 0, 0, 0, 0, 0, 0, | |||||
| py_base_new | |||||
| }; | |||||
| mipmap = mipmap && GPU_get_mipmap(); | PyMethodDef BL_Texture::Methods[] = { | ||||
| { NULL, NULL } //Sentinel | |||||
| }; | |||||
| mTexture = img->bindcode[TEXTARGET_TEXTURE_2D]; | PyAttributeDef BL_Texture::Attributes[] = { | ||||
| mType = GL_TEXTURE_2D; | KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", BL_Texture, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity), | ||||
| mUnit = unit; | KX_PYATTRIBUTE_RW_FUNCTION("diffuseFactor", BL_Texture, pyattr_get_diffuse_factor, pyattr_set_diffuse_factor), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("alpha", BL_Texture, pyattr_get_alpha, pyattr_set_alpha), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", BL_Texture, pyattr_get_specular_intensity, pyattr_set_specular_intensity), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("specularFactor", BL_Texture, pyattr_get_specular_factor, pyattr_set_specular_factor), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("hardness", BL_Texture, pyattr_get_hardness, pyattr_set_hardness), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("emit", BL_Texture, pyattr_get_emit, pyattr_set_emit), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("mirror", BL_Texture, pyattr_get_mirror, pyattr_set_mirror), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("normal", BL_Texture, pyattr_get_normal, pyattr_set_normal), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("parallaxBump", BL_Texture, pyattr_get_parallax_bump, pyattr_set_parallax_bump), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("parallaxStep", BL_Texture, pyattr_get_parallax_step, pyattr_set_parallax_step), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("lodBias", BL_Texture, pyattr_get_lod_bias, pyattr_set_lod_bias), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("bindCode", BL_Texture, pyattr_get_bind_code, pyattr_set_bind_code), | |||||
| KX_PYATTRIBUTE_RO_FUNCTION("cubeMap", BL_Texture, pyattr_get_cube_map), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("ior", BL_Texture, pyattr_get_ior, pyattr_set_ior), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("refractionRatio", BL_Texture, pyattr_get_refraction_ratio, pyattr_set_refraction_ratio), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("uvRotation", BL_Texture, pyattr_get_uv_rotation, pyattr_set_uv_rotation), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("uvOffset", BL_Texture, pyattr_get_uv_offset, pyattr_set_uv_offset), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("uvSize", BL_Texture, pyattr_get_uv_size, pyattr_set_uv_size), | |||||
| KX_PYATTRIBUTE_NULL //Sentinel | |||||
| }; | |||||
| ActivateUnit(mUnit); | PyObject *BL_Texture::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->difffac); | |||||
| } | |||||
| if (mTexture != 0) { | int BL_Texture::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| glBindTexture(GL_TEXTURE_2D, mTexture ); | { | ||||
| Validate(); | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| BKE_image_release_ibuf(img, ibuf, NULL); | float val = PyFloat_AsDouble(value); | ||||
| return mOk; | |||||
| } | |||||
| // look for an existing gl image | if (val == -1 && PyErr_Occurred()) { | ||||
| BL_TextureMap::iterator mapLook = g_textureManager.find(img->id.name); | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| if (mapLook != g_textureManager.end()) | return PY_SET_ATTR_FAIL; | ||||
| { | |||||
| if (mapLook->second.gl_texture != 0) | |||||
| { | |||||
| mTexture = mapLook->second.gl_texture; | |||||
| glBindTexture(GL_TEXTURE_2D, mTexture); | |||||
| mOk = IsValid(); | |||||
| BKE_image_release_ibuf(img, ibuf, NULL); | |||||
| return mOk; | |||||
| } | |||||
| } | } | ||||
| mNeedsDeleted = 1; | self->GetMTex()->difffac = val; | ||||
| glGenTextures(1, (GLuint*)&mTexture); | return PY_SET_ATTR_SUCCESS; | ||||
| } | |||||
| #ifdef WITH_DDS | |||||
| if (ibuf->ftype == IMB_FTYPE_DDS) | |||||
| InitGLCompressedTex(ibuf, mipmap); | |||||
| else | |||||
| InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); | |||||
| #else | |||||
| InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); | |||||
| #endif | |||||
| // track created units | |||||
| BL_TextureObject obj; | |||||
| obj.gl_texture = mTexture; | |||||
| obj.ref_buffer = img; | |||||
| g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)img->id.name, obj)); | |||||
| glDisable(GL_TEXTURE_2D); | |||||
| ActivateUnit(0); | |||||
| Validate(); | |||||
| BKE_image_release_ibuf(img, ibuf, NULL); | |||||
| return mOk; | PyObject *BL_Texture::pyattr_get_diffuse_factor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->colfac); | |||||
| } | } | ||||
| void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) | int BL_Texture::pyattr_set_diffuse_factor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| if (!GPU_full_non_power_of_two_support() && (!is_power_of_2_i(x) || !is_power_of_2_i(y)) ) { | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| InitNonPow2Tex(pix, x,y,mipmap); | float val = PyFloat_AsDouble(value); | ||||
| return; | |||||
| } | |||||
| glBindTexture(GL_TEXTURE_2D, mTexture ); | if (val == -1 && PyErr_Occurred()) { | ||||
| if ( mipmap ) { | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| int i; | return PY_SET_ATTR_FAIL; | ||||
| ImBuf *ibuf; | } | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||||
| ibuf = IMB_allocFromBuffer(pix, NULL, x, y); | self->GetMTex()->colfac = val; | ||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| IMB_makemipmap(ibuf, true); | PyObject *BL_Texture::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->alphafac); | |||||
| } | |||||
| for (i = 0; i < ibuf->miptot; i++) { | int BL_Texture::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| ImBuf *mip = IMB_getmipmap(ibuf, i); | { | ||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); | if (val == -1 && PyErr_Occurred()) { | ||||
| } | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| IMB_freeImBuf(ibuf); | return PY_SET_ATTR_FAIL; | ||||
| } | |||||
| else { | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |||||
| glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix ); | |||||
| } | } | ||||
| if (GLEW_EXT_texture_filter_anisotropic) | self->GetMTex()->alphafac = val; | ||||
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); | return PY_SET_ATTR_SUCCESS; | ||||
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |||||
| } | } | ||||
| void BL_Texture::InitGLCompressedTex(ImBuf *ibuf, bool mipmap) | PyObject *BL_Texture::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| #ifndef WITH_DDS | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| // Fall back to uncompressed if DDS isn't enabled | return PyFloat_FromDouble(self->GetMTex()->specfac); | ||||
| InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); | |||||
| return; | |||||
| #else | |||||
| glBindTexture(GL_TEXTURE_2D, mTexture); | |||||
| if (GPU_upload_dxt_texture(ibuf) == 0) { | |||||
| InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); | |||||
| return; | |||||
| } | |||||
| #endif | |||||
| } | } | ||||
| void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) | int BL_Texture::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| int nx= power_of_2_min_i(x); | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| int ny= power_of_2_min_i(y); | float val = PyFloat_AsDouble(value); | ||||
| ImBuf *ibuf = IMB_allocFromBuffer(pix, NULL, x, y); | |||||
| IMB_scaleImBuf(ibuf, nx, ny); | |||||
| glBindTexture(GL_TEXTURE_2D, mTexture ); | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| if ( mipmap ) { | self->GetMTex()->specfac = val; | ||||
| int i; | return PY_SET_ATTR_SUCCESS; | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | } | ||||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||||
| IMB_makemipmap(ibuf, true); | PyObject *BL_Texture::pyattr_get_specular_factor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->colspecfac); | |||||
| } | |||||
| for (i = 0; i < ibuf->miptot; i++) { | int BL_Texture::pyattr_set_specular_factor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| ImBuf *mip = IMB_getmipmap(ibuf, i); | { | ||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); | if (val == -1 && PyErr_Occurred()) { | ||||
| } | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| } | return PY_SET_ATTR_FAIL; | ||||
| 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, ibuf->rect ); | |||||
| } | } | ||||
| if (GLEW_EXT_texture_filter_anisotropic) | self->GetMTex()->colspecfac = val; | ||||
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); | return PY_SET_ATTR_SUCCESS; | ||||
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |||||
| IMB_freeImBuf(ibuf); | |||||
| } | } | ||||
| PyObject *BL_Texture::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->hardfac); | |||||
| } | |||||
| bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) | int BL_Texture::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| if (!GLEW_ARB_texture_cube_map) | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| { | float val = PyFloat_AsDouble(value); | ||||
| spit("cubemaps not supported"); | |||||
| mOk = false; | |||||
| return mOk; | |||||
| } | |||||
| else if (!cubemap || cubemap->ima->ok==0) | |||||
| { | |||||
| mOk = false; | |||||
| return mOk; | |||||
| } | |||||
| ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL); | if (val == -1 && PyErr_Occurred()) { | ||||
| if (ibuf==0) | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| { | return PY_SET_ATTR_FAIL; | ||||
| cubemap->ima->ok = 0; | |||||
| mOk = false; | |||||
| return mOk; | |||||
| } | } | ||||
| mNeedsDeleted = 1; | self->GetMTex()->hardfac = val; | ||||
| mType = GL_TEXTURE_CUBE_MAP_ARB; | return PY_SET_ATTR_SUCCESS; | ||||
| mTexture = 0; | } | ||||
| mUnit = unit; | |||||
| ActivateUnit(mUnit); | |||||
| BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name); | PyObject *BL_Texture::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| if (mapLook != g_textureManager.end()) | { | ||||
| { | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima) | return PyFloat_FromDouble(self->GetMTex()->emitfac); | ||||
| { | } | ||||
| mTexture = mapLook->second.gl_texture; | |||||
| glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); | |||||
| mOk = IsValid(); | |||||
| BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); | |||||
| return mOk; | |||||
| } | |||||
| } | |||||
| int BL_Texture::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| glGenTextures(1, (GLuint*)&mTexture); | if (val == -1 && PyErr_Occurred()) { | ||||
| glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->GetMTex()->emitfac = val; | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| // track created units | PyObject *BL_Texture::pyattr_get_mirror(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| BL_TextureObject obj; | { | ||||
| obj.gl_texture = mTexture; | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| obj.ref_buffer = cubemap->ima; | return PyFloat_FromDouble(self->GetMTex()->mirrfac); | ||||
| g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj)); | } | ||||
| int BL_Texture::pyattr_set_mirror(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| bool needs_split = false; | if (val == -1 && PyErr_Occurred()) { | ||||
| if (!cubemap->cube[0]) | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| { | return PY_SET_ATTR_FAIL; | ||||
| needs_split = true; | |||||
| spit ("Re-Generating texture buffer"); | |||||
| } | } | ||||
| if (needs_split) | self->GetMTex()->mirrfac = val; | ||||
| my_envmap_split_ima(cubemap, ibuf); | return PY_SET_ATTR_SUCCESS; | ||||
| } | |||||
| PyObject *BL_Texture::pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->norfac); | |||||
| } | |||||
| if (!is_power_of_2_i(cubemap->cube[0]->x) || !is_power_of_2_i(cubemap->cube[0]->y)) | int BL_Texture::pyattr_set_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| spit("invalid envmap size please render with CubeRes @ power of two"); | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| float val = PyFloat_AsDouble(value); | |||||
| my_free_envmapdata(cubemap); | if (val == -1 && PyErr_Occurred()) { | ||||
| mOk = false; | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); | return PY_SET_ATTR_FAIL; | ||||
| return mOk; | |||||
| } | } | ||||
| self->GetMTex()->norfac = val; | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| #define SetCubeMapFace(face, num) \ | PyObject *BL_Texture::pyattr_get_parallax_bump(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| glTexImage2D(face, 0,GL_RGBA, \ | { | ||||
| cubemap->cube[num]->x, \ | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| cubemap->cube[num]->y, \ | return PyFloat_FromDouble(self->GetMTex()->parallaxbumpsc); | ||||
| 0, GL_RGBA, GL_UNSIGNED_BYTE, \ | } | ||||
| cubemap->cube[num]->rect) | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5); | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3); | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0); | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1); | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2); | |||||
| SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4); | |||||
| 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_CLAMP_TO_EDGE ); | |||||
| glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); | |||||
| if (GLEW_VERSION_1_2) | |||||
| glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); | |||||
| if (needs_split) | int BL_Texture::pyattr_set_parallax_bump(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| my_free_envmapdata(cubemap); | { | ||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| if (val == -1 && PyErr_Occurred()) { | |||||
| PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->GetMTex()->parallaxbumpsc = val; | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| glDisable(GL_TEXTURE_CUBE_MAP_ARB); | PyObject *BL_Texture::pyattr_get_parallax_step(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| ActivateUnit(0); | { | ||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->parallaxsteps); | |||||
| } | |||||
| mOk = IsValid(); | int BL_Texture::pyattr_set_parallax_step(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| float val = PyFloat_AsDouble(value); | |||||
| BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); | if (val == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| return mOk; | self->GetMTex()->parallaxsteps = val; | ||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | } | ||||
| bool BL_Texture::IsValid() | PyObject *BL_Texture::pyattr_get_lod_bias(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| return (mTexture!= 0)?glIsTexture(mTexture)!=0:false; | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| return PyFloat_FromDouble(self->GetMTex()->lodbias); | |||||
| } | } | ||||
| int BL_Texture::pyattr_set_lod_bias(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| void BL_Texture::Validate() | |||||
| { | { | ||||
| mOk = IsValid(); | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| } | float val = PyFloat_AsDouble(value); | ||||
| if (val == -1 && PyErr_Occurred()) { | |||||
| PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| bool BL_Texture::Ok() | self->GetMTex()->lodbias = val; | ||||
| { | return PY_SET_ATTR_SUCCESS; | ||||
| return (mTexture!= 0); | |||||
| } | } | ||||
| PyObject *BL_Texture::pyattr_get_bind_code(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| unsigned int BL_Texture::GetTextureType() const | |||||
| { | { | ||||
| return mType; | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| self->CheckValidTexture(); | |||||
| return PyLong_FromLong(self->m_bindCode); | |||||
| } | } | ||||
| int BL_Texture::GetMaxUnits() | int BL_Texture::pyattr_set_bind_code(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| if (g_max_units < 0) { | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| GLint unit = 0; | int val = PyLong_AsLong(value); | ||||
| glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &unit); | |||||
| g_max_units = (MAXTEX >= unit) ? unit : MAXTEX; | if (val < 0 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_AttributeError, "texture.%s = int: BL_Texture, expected a unsigned int", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | } | ||||
| return g_max_units; | self->m_bindCode = val; | ||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | } | ||||
| void BL_Texture::ActivateFirst() | PyObject *BL_Texture::pyattr_get_cube_map(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| if (GLEW_ARB_multitexture) | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB); | KX_CubeMap *cubeMap = (KX_CubeMap *)self->GetCubeMap(); | ||||
| if (cubeMap) { | |||||
| return cubeMap->GetProxy(); | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | } | ||||
| void BL_Texture::ActivateUnit(int unit) | PyObject *BL_Texture::pyattr_get_ior(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| if (GLEW_ARB_multitexture) | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| if (unit <= MAXTEX) | return PyFloat_FromDouble(self->GetMTex()->ior); | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB+unit); | |||||
| } | } | ||||
| int BL_Texture::pyattr_set_ior(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| void BL_Texture::DisableUnit() | |||||
| { | { | ||||
| if (GLEW_ARB_multitexture) | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB+mUnit); | float val = PyFloat_AsDouble(value); | ||||
| glMatrixMode(GL_TEXTURE); | |||||
| glLoadIdentity(); | |||||
| glMatrixMode(GL_MODELVIEW); | |||||
| if (GLEW_ARB_texture_cube_map && glIsEnabled(GL_TEXTURE_CUBE_MAP_ARB)) | if (val == -1 && PyErr_Occurred()) { | ||||
| glDisable(GL_TEXTURE_CUBE_MAP_ARB); | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| else | return PY_SET_ATTR_FAIL; | ||||
| { | |||||
| if (glIsEnabled(GL_TEXTURE_2D)) | |||||
| glDisable(GL_TEXTURE_2D); | |||||
| } | } | ||||
| glDisable(GL_TEXTURE_GEN_S); | CLAMP(val, 1.0, 50.0); | ||||
| glDisable(GL_TEXTURE_GEN_T); | self->GetMTex()->ior = val; | ||||
| glDisable(GL_TEXTURE_GEN_R); | return PY_SET_ATTR_SUCCESS; | ||||
| glDisable(GL_TEXTURE_GEN_Q); | |||||
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |||||
| } | } | ||||
| PyObject *BL_Texture::pyattr_get_refraction_ratio(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->refrratio); | |||||
| } | |||||
| void BL_Texture::DisableAllTextures() | int BL_Texture::pyattr_set_refraction_ratio(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| for (int i=0; i<MAXTEX; i++) { | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| if (GLEW_ARB_multitexture) | float val = PyFloat_AsDouble(value); | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB+i); | |||||
| glMatrixMode(GL_TEXTURE); | if (val == -1 && PyErr_Occurred()) { | ||||
| glLoadIdentity(); | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| glMatrixMode(GL_MODELVIEW); | return PY_SET_ATTR_FAIL; | ||||
| glDisable(GL_TEXTURE_2D); | |||||
| glDisable(GL_TEXTURE_GEN_S); | |||||
| glDisable(GL_TEXTURE_GEN_T); | |||||
| glDisable(GL_TEXTURE_GEN_R); | |||||
| glDisable(GL_TEXTURE_GEN_Q); | |||||
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | |||||
| } | } | ||||
| CLAMP(val, 0.0, 1.0); | |||||
| if (GLEW_ARB_multitexture) | self->GetMTex()->refrratio = val; | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB); | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *BL_Texture::pyattr_get_uv_rotation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyFloat_FromDouble(self->GetMTex()->rot); | |||||
| } | |||||
| void BL_Texture::ActivateTexture() | int BL_Texture::pyattr_set_uv_rotation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| if (GLEW_ARB_multitexture) | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| glActiveTextureARB(GL_TEXTURE0_ARB+mUnit); | float val = PyFloat_AsDouble(value); | ||||
| if (mType == GL_TEXTURE_CUBE_MAP_ARB && GLEW_ARB_texture_cube_map) | if (val == -1 && PyErr_Occurred()) { | ||||
| { | PyErr_Format(PyExc_AttributeError, "texture.%s = float: BL_Texture, expected a float", attrdef->m_name.c_str()); | ||||
| glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture ); | return PY_SET_ATTR_FAIL; | ||||
| glEnable(GL_TEXTURE_CUBE_MAP_ARB); | |||||
| } | } | ||||
| else { | self->GetMTex()->rot = val; | ||||
| if (GLEW_ARB_texture_cube_map ) | return PY_SET_ATTR_SUCCESS; | ||||
| glDisable(GL_TEXTURE_CUBE_MAP_ARB); | } | ||||
| #ifdef USE_MATHUTILS | |||||
| glBindTexture( GL_TEXTURE_2D, mTexture ); | #define MATHUTILS_VEC_CB_TEXTURE_UV_OFFSET_VECTOR 1 | ||||
| glEnable(GL_TEXTURE_2D); | #define MATHUTILS_VEC_CB_TEXTURE_UV_SIZE_VECTOR 2 | ||||
| static unsigned char mathutils_bltexture_cb_index = -1; // Index for our callbacks | |||||
| static int mathutils_bltexture_generic_check(BaseMathObject *bmo) | |||||
| { | |||||
| BL_Texture *self = static_cast<BL_Texture *>BGE_PROXY_REF(bmo->cb_user); | |||||
| if (!self) { | |||||
| return -1; | |||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| void BL_Texture::SetMapping(int mode) | static int mathutils_bltexture_get(BaseMathObject *bmo, int subtype) | ||||
| { | { | ||||
| BL_Texture *self = static_cast<BL_Texture *>BGE_PROXY_REF(bmo->cb_user); | |||||
| if (!(mode &USEREFL)) { | if (!self) { | ||||
| glDisable(GL_TEXTURE_GEN_S); | return -1; | ||||
| glDisable(GL_TEXTURE_GEN_T); | |||||
| glDisable(GL_TEXTURE_GEN_R); | |||||
| glDisable(GL_TEXTURE_GEN_Q); | |||||
| return; | |||||
| } | } | ||||
| if ( mType == GL_TEXTURE_CUBE_MAP_ARB && | switch (subtype) { | ||||
| GLEW_ARB_texture_cube_map && | case MATHUTILS_VEC_CB_TEXTURE_UV_OFFSET_VECTOR: | ||||
| mode &USEREFL) | { | ||||
| { | copy_v3_v3(bmo->data, self->GetMTex()->ofs); | ||||
| glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB ); | break; | ||||
| glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB ); | } | ||||
| glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB ); | case MATHUTILS_VEC_CB_TEXTURE_UV_SIZE_VECTOR: | ||||
| { | |||||
| glEnable(GL_TEXTURE_GEN_S); | copy_v3_v3(bmo->data, self->GetMTex()->size); | ||||
| glEnable(GL_TEXTURE_GEN_T); | break; | ||||
| glEnable(GL_TEXTURE_GEN_R); | } | ||||
| glDisable(GL_TEXTURE_GEN_Q); | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| 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); | |||||
| glDisable(GL_TEXTURE_GEN_R); | |||||
| glDisable(GL_TEXTURE_GEN_Q); | |||||
| } | } | ||||
| } | |||||
| return 0; | |||||
| } | |||||
| void BL_Texture::setTexEnv(BL_Material *mat, bool modulate) | static int mathutils_bltexture_set(BaseMathObject *bmo, int subtype) | ||||
| { | { | ||||
| if (modulate || !GLEW_ARB_texture_env_combine) { | BL_Texture *self = static_cast<BL_Texture *>BGE_PROXY_REF(bmo->cb_user); | ||||
| glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); | if (!self) { | ||||
| return; | return -1; | ||||
| } | } | ||||
| if (glIsList(mEnvState)) | switch (subtype) { | ||||
| { | case MATHUTILS_VEC_CB_TEXTURE_UV_OFFSET_VECTOR: | ||||
| glCallList(mEnvState); | { | ||||
| return; | copy_v3_v3(self->GetMTex()->ofs, bmo->data); | ||||
| } | break; | ||||
| if (!mEnvState) | |||||
| mEnvState = glGenLists(1); | |||||
| glNewList(mEnvState, GL_COMPILE_AND_EXECUTE); | |||||
| glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); | |||||
| GLfloat blend_operand = GL_SRC_COLOR; | |||||
| GLfloat blend_operand_prev = GL_SRC_COLOR; | |||||
| GLfloat alphaOp = GL_SRC_ALPHA; | |||||
| 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 ( mat->flag[mUnit] &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 (mat->flag[mUnit] &TEXNEG) { | |||||
| blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA; | |||||
| blend_operand = GL_ONE_MINUS_SRC_ALPHA; | |||||
| } | } | ||||
| } | case MATHUTILS_VEC_CB_TEXTURE_UV_SIZE_VECTOR: | ||||
| else { | { | ||||
| if (mat->flag[mUnit] &TEXNEG) { | copy_v3_v3(self->GetMTex()->size, bmo->data); | ||||
| blend_operand_prev=GL_ONE_MINUS_SRC_COLOR; | break; | ||||
| blend_operand = GL_ONE_MINUS_SRC_COLOR; | |||||
| } | } | ||||
| } | } | ||||
| bool using_alpha = false; | |||||
| if (mat->flag[mUnit] &USEALPHA) { | return 0; | ||||
| alphaOp = GL_ONE_MINUS_SRC_ALPHA; | } | ||||
| using_alpha=true; | |||||
| } | |||||
| else if (mat->flag[mUnit] &USENEGALPHA) { | |||||
| alphaOp = GL_SRC_ALPHA; | |||||
| using_alpha = true; | |||||
| } | |||||
| switch (mat->blend_mode[mUnit]) { | static int mathutils_bltexture_get_index(BaseMathObject *bmo, int subtype, int index) | ||||
| case BLEND_MIX: | { | ||||
| { | if (mathutils_bltexture_get(bmo, subtype) == -1) { | ||||
| // ------------------------------ | return -1; | ||||
| if (!using_alpha) { | |||||
| GLfloat base_col[4]; | |||||
| base_col[0] = base_col[1] = base_col[2] = 0.f; | |||||
| base_col[3] = 1.f-mat->color_blend[mUnit]; | |||||
| 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); | |||||
| if (!using_alpha) | |||||
| glTexEnvf( GL_TEXTURE_ENV, source2, GL_CONSTANT_ARB ); | |||||
| else | |||||
| glTexEnvf( GL_TEXTURE_ENV, source2, GL_TEXTURE ); | |||||
| glTexEnvf( GL_TEXTURE_ENV, op2, alphaOp); | |||||
| }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 ); | |||||
| if (using_alpha) | |||||
| glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); | |||||
| else | |||||
| 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 ); | |||||
| if (using_alpha) | |||||
| glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); | |||||
| else | |||||
| 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 ); | |||||
| if (using_alpha) | |||||
| glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); | |||||
| else | |||||
| glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); | |||||
| } break; | |||||
| } | } | ||||
| glTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); | return 0; | ||||
| glEndList(); | |||||
| } | } | ||||
| int BL_Texture::GetPow2(int n) | static int mathutils_bltexture_set_index(BaseMathObject *bmo, int subtype, int index) | ||||
| { | { | ||||
| if (!is_power_of_2_i(n)) | float f = bmo->data[index]; | ||||
| n = power_of_2_min_i(n); | |||||
| if (mathutils_bltexture_get(bmo, subtype) == -1) { | |||||
| return -1; | |||||
| } | |||||
| return n; | bmo->data[index] = f; | ||||
| return mathutils_bltexture_set(bmo, subtype); | |||||
| } | } | ||||
| void BL_Texture::SplitEnvMap(EnvMap *map) | static Mathutils_Callback mathutils_bltexture_cb = { | ||||
| mathutils_bltexture_generic_check, | |||||
| mathutils_bltexture_get, | |||||
| mathutils_bltexture_set, | |||||
| mathutils_bltexture_get_index, | |||||
| mathutils_bltexture_set_index | |||||
| }; | |||||
| void BL_Texture_Mathutils_Callback_Init() | |||||
| { | { | ||||
| if (!map || !map->ima || (map->ima && !map->ima->ok)) return; | // Register mathutils callbacks, ok to run more than once. | ||||
| ImBuf *ibuf= BKE_image_acquire_ibuf(map->ima, NULL, NULL); | mathutils_bltexture_cb_index = Mathutils_RegisterCallback(&mathutils_bltexture_cb); | ||||
| if (ibuf) { | |||||
| my_envmap_split_ima(map, ibuf); | |||||
| BKE_image_release_ibuf(map->ima, ibuf, NULL); | |||||
| } | |||||
| } | } | ||||
| unsigned int BL_Texture::mDisableState = 0; | #endif // USE_MATHUTILS | ||||
| extern "C" { | PyObject *BL_Texture::pyattr_get_uv_offset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| #ifdef USE_MATHUTILS | |||||
| return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_bltexture_cb_index, MATHUTILS_VEC_CB_TEXTURE_UV_OFFSET_VECTOR); | |||||
| #else | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf) | return PyObjectFrom(MT_Vector3(self->GetMTex()->ofs)); | ||||
| #endif | |||||
| } | |||||
| int BL_Texture::pyattr_set_uv_offset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | { | ||||
| int dx, part; | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| MT_Vector3 offset; | |||||
| my_free_envmapdata(env); | if (!PyVecTo(value, offset)) { | ||||
| return PY_SET_ATTR_FAIL; | |||||
| dx= ibuf->y; | |||||
| dx/= 2; | |||||
| if (3*dx != ibuf->x) { | |||||
| printf("Incorrect envmap size\n"); | |||||
| env->ok= 0; | |||||
| env->ima->ok= 0; | |||||
| } | |||||
| else { | |||||
| for (part=0; part<6; part++) { | |||||
| env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect); | |||||
| } | |||||
| IMB_rectcpy(env->cube[0], ibuf, | |||||
| 0, 0, 0, 0, dx, dx); | |||||
| IMB_rectcpy(env->cube[1], ibuf, | |||||
| 0, 0, dx, 0, dx, dx); | |||||
| IMB_rectcpy(env->cube[2], ibuf, | |||||
| 0, 0, 2*dx, 0, dx, dx); | |||||
| IMB_rectcpy(env->cube[3], ibuf, | |||||
| 0, 0, 0, dx, dx, dx); | |||||
| IMB_rectcpy(env->cube[4], ibuf, | |||||
| 0, 0, dx, dx, dx, dx); | |||||
| IMB_rectcpy(env->cube[5], ibuf, | |||||
| 0, 0, 2*dx, dx, dx, dx); | |||||
| env->ok= 2;// ENV_OSA | |||||
| } | } | ||||
| offset.getValue(self->GetMTex()->ofs); | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | } | ||||
| PyObject *BL_Texture::pyattr_get_uv_size(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| #ifdef USE_MATHUTILS | |||||
| return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_bltexture_cb_index, MATHUTILS_VEC_CB_TEXTURE_UV_SIZE_VECTOR); | |||||
| #else | |||||
| BL_Texture *self = static_cast<BL_Texture *>(self_v); | |||||
| return PyObjectFrom(MT_Vector3(self->GetMTex()->size)); | |||||
| #endif | |||||
| } | |||||
| void my_free_envmapdata(EnvMap *env) | int BL_Texture::pyattr_set_uv_size(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| unsigned int part; | BL_Texture *self = static_cast<BL_Texture *>(self_v); | ||||
| MT_Vector3 size; | |||||
| for (part=0; part<6; part++) { | if (!PyVecTo(value, size)) { | ||||
| ImBuf *ibuf= env->cube[part]; | return PY_SET_ATTR_FAIL; | ||||
| if (ibuf) { | |||||
| IMB_freeImBuf(ibuf); | |||||
| env->cube[part] = NULL; | |||||
| } | |||||
| } | } | ||||
| env->ok= 0; | |||||
| } | |||||
| size.getValue(self->GetMTex()->size); | |||||
| } // extern C | return PY_SET_ATTR_SUCCESS; | ||||
| } | |||||
| #endif // WITH_PYTHON | |||||
| Context not available. | |||||