diff options
author | Erwin Coumans <blender@erwincoumans.com> | 2006-01-08 12:37:15 +0300 |
---|---|---|
committer | Erwin Coumans <blender@erwincoumans.com> | 2006-01-08 12:37:15 +0300 |
commit | c94455c14d28221f6e05f33ba42e23a5d3245a28 (patch) | |
tree | 733dfaccbbcd71cf66e2d33b1868f64f78189eeb /source/gameengine/Ketsji/BL_Texture.cpp | |
parent | 88a8508b347dda050557e72dfad105023e5095aa (diff) |
more linux game engine work. hopefully works now!
Diffstat (limited to 'source/gameengine/Ketsji/BL_Texture.cpp')
-rw-r--r-- | source/gameengine/Ketsji/BL_Texture.cpp | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp new file mode 100644 index 00000000000..f03bfffc8ec --- /dev/null +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -0,0 +1,389 @@ +// ------------------------------------ +#ifdef WIN32 +#include <windows.h> +#endif // WIN32 +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif + +#include <iostream> + +#include "BL_Material.h" +#include "BL_Texture.h" +#include "MT_assert.h" + +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "IMB_imbuf_types.h" +#include "BKE_image.h" +//#include "IMB_imbuf.h" +#include "BLI_blenlib.h" + +#include "RAS_GLExtensionManager.h" +using namespace bgl; + +#define spit(x) std::cout << x << std::endl; + +#include "MEM_guardedalloc.h" + + + +extern "C" { + // envmaps + #include "IMB_imbuf.h" + void my_envmap_split_ima(EnvMap *env); + void my_free_envmapdata(EnvMap *env); +} + +// (n&(n-1)) zeros the least significant bit of n +static int is_pow2(int num) { + return ((num)&(num-1))==0; +} +static int smaller_pow2(int num) { + while (!is_pow2(num)) + num= num&(num-1); + return num; +} + + + +BL_Texture::BL_Texture() +: mTexture(0), + mError(0), + mOk(0), + mNeedsDeleted(0), + mType(0), + mName("") +{ + // -- +} + +BL_Texture::~BL_Texture() +{ + // -- +} + +void BL_Texture::DeleteTex() +{ + if( mNeedsDeleted ) { + glDeleteTextures(1, (GLuint*)&(*mTexture)); + mNeedsDeleted = 0; + mOk = 0; + } +} + + +bool BL_Texture::InitFromImage( Image *img, bool mipmap) +{ + if(!img || img->ok==0 ) { + mError = true; + mOk = false; + return mOk; + } + if( img->ibuf==0 ) { + load_image(img, IB_rect, "", 0); + if(img->ibuf==0) { + img->ok = 0; + mError = true; + mOk = false; + return mOk; + } + } + mTexture = &img->bindcode; + mName = img->id.name; + mType = BL_TEX2D; + + // smoke em if we got em + if (*mTexture != 0) { + glBindTexture(GL_TEXTURE_2D, *mTexture ); + Validate(); + return mOk; + } + glGenTextures(1, (GLuint*)mTexture); + InitGLTex(img->ibuf->rect, img->ibuf->x, img->ibuf->y, mipmap); + Validate(); + return mOk; +} + +void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) +{ + if (!is_pow2(x) || !is_pow2(y) ) { + InitNonPow2Tex(pix, x,y,mipmap); + return; + } + + glBindTexture(GL_TEXTURE_2D, *mTexture ); + if( mipmap ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + + +void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) +{ + int nx= smaller_pow2(x); + int ny= smaller_pow2(y); + + unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int)); + + gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels); + glBindTexture(GL_TEXTURE_2D, *mTexture ); + + if( mipmap ) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + free(newPixels); +} + + +bool BL_Texture::InitCubeMap( EnvMap *cubemap ) +{ +#ifdef GL_ARB_texture_cube_map + if(!RAS_EXT_support._ARB_texture_cube_map) { + spit("cubemaps not supported"); + mError = true; + mOk = false; + return mOk; + } + + else if(!cubemap || cubemap->ima->ok==0 ) { + mError = true; + mOk = false; + return mOk; + } + + if( cubemap->ima->ibuf==0 ) { + load_image(cubemap->ima, IB_rect, "", 0); + if(cubemap->ima->ibuf==0) { + cubemap->ima->ok = 0; + mError = true; + mOk = false; + return mOk; + } + } + + EnvMap *CubeMap = cubemap; + mNeedsDeleted = 1; + mBlankTexture = 0; + mType = BL_TEXCUBE; + mTexture = &mBlankTexture; + mName = CubeMap->ima->id.name; + + glGenTextures(1, (GLuint*)(mTexture)); + glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *mTexture ); + bool needs_split = false; + + if(!CubeMap->cube[0]) needs_split = true; + + if(needs_split){ + // split it + my_envmap_split_ima(CubeMap); + } + + int x = cubemap->ima->ibuf->x; + int y = cubemap->ima->ibuf->y; + unsigned int *data= (unsigned int *)malloc(x*y*sizeof(unsigned int)); + + // ----------------------------------- + x = CubeMap->cube[0]->ibuf->x; + y = CubeMap->cube[0]->ibuf->y; + + // check the first image, and assume the rest + if (!is_pow2(x) || !is_pow2(y)) + { + spit("invalid envmap size please render with CubeRes @ power of two"); + free(data); + data = 0; + mError = true; + mOk = false; + return mOk; + } + memcpy(data, CubeMap->cube[0]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[1]->ibuf->x; + y = CubeMap->cube[1]->ibuf->y; + memcpy(data, CubeMap->cube[1]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[2]->ibuf->x; + y = CubeMap->cube[2]->ibuf->y; + memcpy(data, CubeMap->cube[2]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[3]->ibuf->x; + y = CubeMap->cube[3]->ibuf->y; + memcpy(data, CubeMap->cube[3]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[4]->ibuf->x; + y = CubeMap->cube[4]->ibuf->y; + memcpy(data, CubeMap->cube[4]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + // ----------------------------------- + x = CubeMap->cube[5]->ibuf->x; + y = CubeMap->cube[5]->ibuf->y; + memcpy(data, CubeMap->cube[5]->ibuf->rect, (x*y*sizeof(unsigned int))); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT ); + + if(data) { + free(data); + data = 0; + } + + if(needs_split) { + // okay we allocated, swap back to orig and free used + cubemap->ima = CubeMap->ima; + my_free_envmapdata(CubeMap); + } + mOk = IsValid(); + return mOk; + +#else + + mError = true; + mOk = false; + return mOk; + +#endif//GL_ARB_texture_cube_map +} + + +STR_String BL_Texture::GetName() const +{ + return mName; +} + + +bool BL_Texture::IsValid() +{ + return (mTexture && *mTexture!= 0)?glIsTexture(*mTexture)!=0:false; +} + + +void BL_Texture::Validate() +{ + mOk = IsValid(); +} + + +bool BL_Texture::Ok() +{ + return ( mTexture?((!mError || mOk ) && *mTexture!= 0):0 ); +} + + +unsigned int BL_Texture::GetTextureType() const +{ + return mType; +} + + +BL_Texture::operator const unsigned int () const +{ + return mTexture? *mTexture:0; +} + +bool BL_Texture::SetGLTex(unsigned int tex) +{ + return false; +} + +extern "C" { + +void my_envmap_split_ima(EnvMap *env) +{ + ImBuf *ibuf; + Image *ima; + int dx, part; + + my_free_envmapdata(env); + + dx= env->ima->ibuf->y; + dx/= 2; + if(3*dx != env->ima->ibuf->x) { + printf("Incorrect envmap size\n"); + env->ok= 0; + env->ima->ok= 0; + } + else { + for(part=0; part<6; part++) { + ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0); + ima= (Image*)MEM_callocN(sizeof(Image), "image"); + ima->ibuf= ibuf; + ima->ok= 1; + env->cube[part]= ima; + } + IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf, + 0, 0, 0, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf, + 0, 0, dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf, + 0, 0, 0, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf, + 0, 0, dx, dx, dx, dx, IMB_rectcpy, 0); + IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf, + 0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0); + env->ok= 2; + } +} + + +void my_free_envmapdata(EnvMap *env) +{ + Image *ima; + unsigned int a, part; + + for(part=0; part<6; part++) { + ima= env->cube[part]; + if(ima) { + if(ima->ibuf) IMB_freeImBuf(ima->ibuf); + + for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + } + MEM_freeN(ima); + env->cube[part]= 0; + } + } + env->ok= 0; +} + + +} + +unsigned int BL_Texture::mBlankTexture = 0; + |