/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "GPC_PolygonMaterial.h" #include "MT_Vector3.h" #include "RAS_IRasterizer.h" /* This list includes only data type definitions */ #include "DNA_object_types.h" #include "DNA_material_types.h" #include "DNA_image_types.h" #include "DNA_lamp_types.h" #include "DNA_group_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" #include "DNA_property_types.h" #include "DNA_text_types.h" #include "DNA_sensor_types.h" #include "DNA_controller_types.h" #include "DNA_actuator_types.h" #include "DNA_mesh_types.h" #include "DNA_view3d_types.h" #include "DNA_world_types.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_mesh.h" #include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" /* end of blender include block */ #ifdef WIN32 #include #endif // WIN32 #include "GL/gl.h" #include "GL/glu.h" static Image *fCurpage=0; static int fCurtile=0, fCurmode=0, fCurTileXRep=0, fCurTileYRep=0; static short fTexWindx, fTexWindy, fTexWinsx, fTexWinsy; static int fDoMipMap = 1; static int fLinearMipMap=1; static int fAlphamode= -1; /* (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; } static void my_make_repbind(Image *ima) { if(ima==0 || ima->ibuf==0) return; if(ima->repbind) { glDeleteTextures(ima->totbind, (GLuint*)ima->repbind); delete (ima->repbind); ima->repbind= 0; } ima->totbind= ima->xrep*ima->yrep; if(ima->totbind>1) { ima->repbind= (unsigned int *) malloc(sizeof(int)*ima->totbind); for (int i=0;itotbind;i++) ((int*)ima->repbind)[i] = 0; } } int my_set_tpage(TFace *tface) { static TFace *lasttface= 0; Image *ima; unsigned int *rect, *bind; int tpx, tpy, tilemode, tileXRep,tileYRep; /* afschakelen */ if(tface==0) { if(lasttface==0) return 0; lasttface= 0; fCurtile= 0; fCurpage= 0; if(fCurmode!=0) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); } fCurmode= 0; fCurTileXRep=0; fCurTileYRep=0; fAlphamode= -1; glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); return 0; } lasttface= tface; if( fAlphamode != tface->transp) { fAlphamode= tface->transp; if(fAlphamode) { glEnable(GL_BLEND); if(fAlphamode==TF_ADD) { glBlendFunc(GL_ONE, GL_ONE); /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ } else if(fAlphamode==TF_ALPHA) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ } /* else { */ /* glBlendFunc(GL_ONE, GL_ONE); */ /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */ /* } */ } else glDisable(GL_BLEND); } ima= (struct Image *) tface->tpage; /* Enable or disable environment mapping */ if (ima && (ima->flag & IMA_REFLECT)){ 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); } else{ glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); } tilemode= tface->mode & TF_TILES; tileXRep = 0; tileYRep = 0; if (ima) { tileXRep = ima->xrep; tileYRep = ima->yrep; } if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurTileXRep==tileXRep && fCurTileYRep == tileYRep) return ima!=0; if(tilemode!=fCurmode || fCurTileXRep!=tileXRep || fCurTileYRep != tileYRep) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); if(tilemode && ima!=0) glScalef(ima->xrep, ima->yrep, 1.0); glMatrixMode(GL_MODELVIEW); } if(ima==0 || ima->ok==0) { glDisable(GL_TEXTURE_2D); fCurtile= tface->tile; fCurpage= 0; fCurmode= tilemode; fCurTileXRep = tileXRep; fCurTileYRep = tileYRep; return 0; } if(ima->ibuf==0) { load_image(ima, IB_rect, "", 0); if(ima->ibuf==0) { ima->ok= 0; fCurtile= tface->tile; fCurpage= 0; fCurmode= tilemode; fCurTileXRep = tileXRep; fCurTileYRep = tileYRep; glDisable(GL_TEXTURE_2D); return 0; } } if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe; else fCurtile= tface->tile; if(tilemode) { if(ima->repbind==0) my_make_repbind(ima); if(fCurtile>=ima->totbind) fCurtile= 0; /* this happens when you change repeat buttons */ if(ima->repbind) bind= ima->repbind+fCurtile; else bind= &ima->bindcode; if(*bind==0) { fTexWindx= ima->ibuf->x/ima->xrep; fTexWindy= ima->ibuf->y/ima->yrep; if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1; fTexWinsy= fCurtile / ima->xrep; fTexWinsx= fCurtile - fTexWinsy*ima->xrep; fTexWinsx*= fTexWindx; fTexWinsy*= fTexWindy; tpx= fTexWindx; tpy= fTexWindy; rect= ima->ibuf->rect + fTexWinsy*ima->ibuf->x + fTexWinsx; } } else { bind= &ima->bindcode; if(*bind==0) { tpx= ima->ibuf->x; tpy= ima->ibuf->y; rect= ima->ibuf->rect; } } if(*bind==0) { int rectw= tpx, recth= tpy; unsigned int *tilerect= NULL, *scalerect= NULL; /* * Maarten: * According to Ton this code is not needed anymore. It was used only * in really old Blenders. * Reevan: * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it. */ #if 1 if (tilemode) { int y; tilerect= (unsigned int*)MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); for (y=0; yibuf->x]; unsigned int *tilerectrow= &tilerect[y*rectw]; memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); } rect= tilerect; } #endif if (!is_pow2(rectw) || !is_pow2(recth)) { rectw= smaller_pow2(rectw); recth= smaller_pow2(recth); scalerect= (unsigned int *)MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); rect= scalerect; } glGenTextures(1, (GLuint*)bind); /* if(G.f & G_DEBUG) { printf("var1: %s\n", ima->id.name+2); printf("var1: %d, var2: %d\n", *bind, tpx); printf("var1: %d, var2: %d\n", fCurtile, tilemode); } */ glBindTexture( GL_TEXTURE_2D, *bind); if (!fDoMipMap) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; gluBuild2DMipmaps(GL_TEXTURE_2D, 4, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (tilerect) MEM_freeN(tilerect); if (scalerect) MEM_freeN(scalerect); } else glBindTexture( GL_TEXTURE_2D, *bind); glEnable(GL_TEXTURE_2D); fCurpage= ima; fCurmode= tilemode; fCurTileXRep = tileXRep; fCurTileYRep = tileYRep; return 1; } GPC_PolygonMaterial::GPC_PolygonMaterial(const STR_String& texname, bool ba, const STR_String& matname, int tile, int tileXrep, int tileYrep, int mode, int transparant, int lightlayer, bool bIsTriangle, void* clientobject, void* tpage) : RAS_IPolyMaterial(texname, ba, matname, tile, tileXrep, tileYrep, mode, transparant, lightlayer, bIsTriangle, clientobject), m_tface((struct TFace*)tpage) { // clear local caching info my_set_tpage(0); } GPC_PolygonMaterial::~GPC_PolygonMaterial(void) { } void GPC_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const { if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) { my_set_tpage(0); } cachingInfo = GetCachingInfo(); if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) ) { update_realtime_texture((struct TFace*) m_tface, rasty->GetTime()); my_set_tpage(m_tface); rasty->EnableTextures(true); } else { my_set_tpage(0); rasty->EnableTextures(false); } //TF_TWOSIDE == 512, todo, make this a ketsji enum if(m_drawingmode & 512) { rasty->SetCullFace(false); } else { rasty->SetCullFace(true);;//glEnable(GL_CULL_FACE); //else glDisable(GL_CULL_FACE); } } rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); rasty->SetShinyness(m_shininess); rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0); } void GPC_PolygonMaterial::SetMipMappingEnabled(bool enabled) { fDoMipMap = enabled ? 1 : 0; }