blender/source/gameengine/GamePlayer/common/GPC_PolygonMaterial.cpp

425 lines
10 KiB
C++
Raw Normal View History

2002-10-12 11:37:38 +00:00
/**
* $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 *****
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
2002-10-12 11:37:38 +00:00
#ifdef WIN32
#include <windows.h>
#endif // WIN32
#ifdef __APPLE__
#define GL_GLEXT_LEGACY 1
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#include "GPC_PolygonMaterial.h"
2002-10-12 11:37:38 +00:00
#include "MT_Vector3.h"
#include "RAS_IRasterizer.h"
#include "RAS_GLExtensionManager.h"
2002-10-12 11:37:38 +00:00
/* 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_meshdata_types.h"
2002-10-12 11:37:38 +00:00
#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 */
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;
using namespace bgl;
2002-10-12 11:37:38 +00:00
/* (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;i<ima->totbind;i++)
((int*)ima->repbind)[i] = 0;
}
}
extern "C" int set_tpage(TFace *tface);
2002-10-12 11:37:38 +00:00
int set_tpage(TFace *tface)
2002-10-12 11:37:38 +00:00
{
static TFace *lasttface= 0;
Image *ima;
unsigned int *rect, *bind;
int tpx, tpy, tilemode, tileXRep,tileYRep;
/* disable */
2002-10-12 11:37:38 +00:00
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; y<recth; y++) {
unsigned int *rectrow= &rect[y*ima->ibuf->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);
2002-10-12 11:37:38 +00:00
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, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
2002-10-12 11:37:38 +00:00
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;
}
#if 0
2002-10-12 11:37:38 +00:00
GPC_PolygonMaterial::GPC_PolygonMaterial(const STR_String& texname, bool ba, const STR_String& matname,
int tile, int tileXrep, int tileYrep, int mode, bool transparant, bool zsort,
2002-10-12 11:37:38 +00:00
int lightlayer, bool bIsTriangle, void* clientobject, void* tpage) :
RAS_IPolyMaterial(texname, ba, matname, tile, tileXrep, tileYrep, mode,
transparant, zsort, lightlayer, bIsTriangle, clientobject), m_tface((struct TFace*)tpage)
2002-10-12 11:37:38 +00:00
{
// 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);
2002-10-12 11:37:38 +00:00
//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);
}
#endif
2002-10-12 11:37:38 +00:00
void GPC_PolygonMaterial::SetMipMappingEnabled(bool enabled)
{
fDoMipMap = enabled ? 1 : 0;
}