diff options
36 files changed, 859 insertions, 873 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index f61b300f708..7dc10c53e22 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -437,5 +437,7 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb); /* determines required DerivedMesh data according to view and edit modes */ CustomDataMask get_viewedit_datamask(); +void DM_add_tangent_layer(DerivedMesh *dm); + #endif diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f76cdbc64b7..d951c8401e3 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 246 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 4d3f9143b85..67cf89d5ee2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -59,6 +59,7 @@ #include "BLI_edgehash.h" #include "BLI_editVert.h" #include "BLI_linklist.h" +#include "BLI_memarena.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" @@ -2844,6 +2845,127 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo return numleft; } +void DM_add_tangent_layer(DerivedMesh *dm) +{ + /* mesh vars */ + MTFace *mtface, *tf; + MFace *mface, *mf; + MVert *mvert, *v1, *v2, *v3, *v4; + MemArena *arena= NULL; + VertexTangent **vtangents= NULL; + float (*orco)[3]= NULL, (*tangent)[3]; + float *uv1, *uv2, *uv3, *uv4, *vtang; + float fno[3], tang[3], uv[4][2]; + int i, j, len, mf_vi[4], totvert, totface; + + if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) + return; + + /* check we have all the needed layers */ + totvert= dm->getNumVerts(dm); + totface= dm->getNumFaces(dm); + + mvert= dm->getVertArray(dm); + mface= dm->getFaceArray(dm); + mtface= dm->getFaceDataArray(dm, CD_MTFACE); + + if(!mtface) { + orco= dm->getVertDataArray(dm, CD_ORCO); + if(!orco) + return; + } + + /* create tangent layer */ + DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL); + tangent= DM_get_face_data_layer(dm, CD_TANGENT); + + /* allocate some space */ + arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + BLI_memarena_use_calloc(arena); + vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent"); + + /* sum tangents at connected vertices */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) { + v1= &mvert[mf->v1]; + v2= &mvert[mf->v2]; + v3= &mvert[mf->v3]; + + if (mf->v4) { + v4= &mvert[mf->v4]; + CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno); + } + else { + v4= NULL; + CalcNormFloat(v3->co, v2->co, v1->co, fno); + } + + if(mtface) { + uv1= tf->uv[0]; + uv2= tf->uv[1]; + uv3= tf->uv[2]; + uv4= tf->uv[3]; + } + else { + uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]); + spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]); + spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]); + if(v4) + spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]); + } + + tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + + if(mf->v4) { + v4= &mvert[mf->v4]; + + tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); + sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4); + } + } + + /* write tangent to layer */ + for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) { + len= (mf->v4)? 4 : 3; + + if(mtface) { + uv1= tf->uv[0]; + uv2= tf->uv[1]; + uv3= tf->uv[2]; + uv4= tf->uv[3]; + } + else { + uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3]; + spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]); + spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]); + spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]); + if(len==4) + spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]); + } + + mf_vi[0]= mf->v1; + mf_vi[1]= mf->v2; + mf_vi[2]= mf->v3; + mf_vi[3]= mf->v4; + + for(j=0; j<len; j++) { + vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]); + + VECCOPY(tangent[j], vtang); + Normalize(tangent[j]); + } + } + + BLI_memarena_free(arena); + MEM_freeN(vtangents); +} + + /* ************************* fluidsim bobj file handling **************************** */ #ifndef DISABLE_ELBEEM diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 501293ecd81..9012adb09b7 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -532,13 +532,14 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol} + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, + {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", - "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol"}; + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"}; const CustomDataMask CD_MASK_BAREMESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; @@ -552,7 +553,7 @@ const CustomDataMask CD_MASK_EDITMESH = const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | - CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO; + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT; const CustomDataMask CD_MASK_BMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; const CustomDataMask CD_MASK_FACECORNERS = diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ad004dd5c82..ad19cde3c9b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4870,6 +4870,49 @@ void idproperties_fix_group_lengths(ListBase idlist) } } +void alphasort_version_246(FileData *fd, Library *lib, Mesh *me) +{ + Material *ma; + MFace *mf; + MTFace *tf; + int a, b, texalpha; + + /* verify we have a tface layer */ + for(b=0; b<me->fdata.totlayer; b++) + if(me->fdata.layers[b].type == CD_MTFACE) + break; + + if(b == me->fdata.totlayer) + return; + + /* if we do, set alpha sort if the game engine did it before */ + for(a=0, mf=me->mface; a<me->totface; a++, mf++) { + if(mf->mat_nr < me->totcol) { + ma= newlibadr(fd, lib, me->mat[mf->mat_nr]); + texalpha = 0; + + for(b=0; ma && b<MAX_MTEX; b++) + if(ma->mtex && ma->mtex[b] && ma->mtex[b]->mapto & MAP_ALPHA) + texalpha = 1; + } + else { + ma= NULL; + texalpha = 0; + } + + for(b=0; b<me->fdata.totlayer; b++) { + if(me->fdata.layers[b].type == CD_MTFACE) { + tf = ((MTFace*)me->fdata.layers[b].data) + a; + + tf->mode &= ~TF_ALPHASORT; + if(ma && (ma->mode & MA_ZTRA)) + if(ELEM(tf->transp, TF_ALPHA, TF_ADD) || (texalpha && (tf->transp != TF_CLIP))) + tf->mode |= TF_ALPHASORT; + } + } + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -7714,8 +7757,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } /* sun/sky */ - if ((main->versionfile < 246) ){ + if(main->versionfile < 246) { Lamp *la; + for(la=main->lamp.first; la; la= la->id.next) { la->sun_effect_type = 0; la->horizon_brightness = 1.0; @@ -7731,6 +7775,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if(main->versionfile <= 246 && main->subversionfile < 1){ + Mesh *me; + + for(me=main->mesh.first; me; me= me->id.next) + alphasort_version_246(fd, lib, me); + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 72557145270..6c098e220bb 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -71,7 +71,8 @@ typedef struct CustomData { #define CD_MTEXPOLY 15 #define CD_MLOOPUV 16 #define CD_MLOOPCOL 17 -#define CD_NUMTYPES 18 +#define CD_TANGENT 18 +#define CD_NUMTYPES 19 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -92,6 +93,7 @@ typedef struct CustomData { #define CD_MASK_MTEXPOLY (1 << CD_MTEXPOLY) #define CD_MASK_MLOOPUV (1 << CD_MLOOPUV) #define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL) +#define CD_MASK_TANGENT (1 << CD_TANGENT) /* CustomData.flag */ diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 6d025839ac8..4e427ed733c 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -228,7 +228,7 @@ typedef struct PartialVisibility { /* mtface->mode */ #define TF_DYNAMIC 1 -#define TF_DEPRECATED 2 +#define TF_ALPHASORT 2 #define TF_TEX 4 #define TF_SHAREDVERT 8 #define TF_LIGHT 16 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 180fdc852ae..b26c52a92e2 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -6189,6 +6189,7 @@ static void editing_panel_mesh_texface(void) uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint"); uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow"); uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face"); + uiDefButBitS(block, TOG, TF_ALPHASORT, REDRAWVIEW3D, "Sort", 840,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable sorting of faces for correct alpha drawing (slow, use Clip Alpha instead when possible)"); uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index ed6ea7c5f6a..da52be56d1b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -170,6 +170,7 @@ void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); + if(glIsEnabled(GL_ALPHA_TEST)) glDisable(GL_ALPHA_TEST); if(glIsEnabled(GL_LIGHTING)) { glDisable(GL_LIGHTING); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp deleted file mode 100644 index d173b1c66d9..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL 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. - * - * 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 LICENSE BLOCK ***** - */ - -#include "KX_BlenderPolyMaterial.h" -#include "BKE_mesh.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#if 0 -KX_BlenderPolyMaterial::KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface) - : RAS_IPolyMaterial(texname, - false, - matname, - tile, - tilexrep, - tileyrep, - mode, - transparant, - zsort, - lightlayer, - bIsTriangle, - clientobject), - m_tface(tface) -{ -} - -void KX_BlenderPolyMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const -{ - - - if (GetCachingInfo() != cachingInfo) - { - if (!cachingInfo) - { - set_tpage(NULL); - } - cachingInfo = GetCachingInfo(); - - if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) - { - update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); - set_tpage(m_tface); - rasty->EnableTextures(true); - } - else - { - set_tpage(NULL); - rasty->EnableTextures(false); - } - - if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - { - rasty->SetCullFace(false); - } - else - { - rasty->SetCullFace(true); - } - - if (m_drawingmode & RAS_IRasterizer::KX_LINES) { - rasty->SetLines(true); - } - else { - rasty->SetLines(false); - } - } - - 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 - - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h deleted file mode 100644 index 35823b2125b..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL 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. - * - * 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 LICENSE BLOCK ***** - */ -#ifndef __KX_BLENDERPOLYMATERIAL -#define __KX_BLENDERPOLYMATERIAL - -#include "RAS_MaterialBucket.h" -#include "RAS_IRasterizer.h" - -struct MTFace; -extern "C" int set_tpage(MTFace* tface); /* Worst hack ever */ - -#if 0 -class KX_BlenderPolyMaterial : public RAS_IPolyMaterial -{ - /** Blender texture face structure. */ - MTFace* m_tface; - -public: - - KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface); - - /** - * Returns the caching information for this material, - * This can be used to speed up the rasterizing process. - * @return The caching information. - */ - virtual TCachingInfo GetCachingInfo(void) const; - - /** - * Activates the material in the (OpenGL) rasterizer. - * On entry, the cachingInfo contains info about the last activated material. - * On exit, the cachingInfo should contain updated info about this material. - * @param rasty The rasterizer in which the material should be active. - * @param cachingInfo The information about the material used to speed up rasterizing. - */ - virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const; - - /** - * Returns the Blender texture face structure that is used for this material. - * @return The material's texture face. - */ - MTFace* GetMTFace(void) const; -protected: -private: -}; - - -inline MTFace* KX_BlenderPolyMaterial::GetMTFace(void) const -{ - return m_tface; -} - -inline RAS_IPolyMaterial::TCachingInfo KX_BlenderPolyMaterial::GetCachingInfo(void) const -{ - return GetMTFace(); -} - -#endif - -#endif // __KX_BLENDERPOLYMATERIAL - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 220d174d464..e4eff163d5b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -40,7 +40,6 @@ // it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" -#include "KX_BlenderPolyMaterial.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 320921722e1..2cc5cfda84c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -136,8 +136,12 @@ #include "BKE_mesh.h" #include "MT_Point3.h" +#include "BLI_arithb.h" + extern "C" { - #include "BKE_customdata.h" +#include "BKE_customdata.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" } #include "BKE_material.h" /* give_current_material */ @@ -309,7 +313,6 @@ typedef struct MTF_localLayer // ------------------------------------ BL_Material* ConvertMaterial( - Mesh* mesh, Material *mat, MTFace* tface, const char *tfaceName, @@ -323,15 +326,16 @@ BL_Material* ConvertMaterial( //this needs some type of manager BL_Material *material = new BL_Material(); - int numchan = -1; + int numchan = -1, texalpha = 0; bool validmat = (mat!=0); - bool validface = (mesh->mtface && tface); + bool validface = (tface!=0); short type = 0; if( validmat ) type = 1; // material color material->IdMode = DEFAULT_BLENDER; + material->glslmat = (validmat)? glslmat: false; // -------------------------------- if(validmat) { @@ -367,12 +371,13 @@ BL_Material* ConvertMaterial( if(i==0 && facetex ) { Image*tmp = (Image*)(tface->tpage); + if(tmp) { material->img[i] = tmp; material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0; + if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; else @@ -430,6 +435,8 @@ BL_Material* ConvertMaterial( material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0; material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0; + if(!glslmat && (material->flag[i] & TEXALPHA)) + texalpha = 1; } } else if(mttmp->tex->type == TEX_ENVMAP) { @@ -546,17 +553,7 @@ BL_Material* ConvertMaterial( material->ref = mat->ref; material->amb = mat->amb; - // set alpha testing without z-sorting - if( ( validface && (!(tface->transp &~ TF_CLIP))) && mat->mode & MA_ZTRA) { - // sets the RAS_IPolyMaterial::m_flag |RAS_FORCEALPHA - // this is so we don't have the overhead of the z-sorting code - material->ras_mode|=ALPHA_TEST; - } - else{ - // use regular z-sorting - material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0; - } - material->ras_mode |= ((mat->mode & MA_WIRE) != 0)?WIRE:0; + material->ras_mode |= (mat->mode & MA_WIRE)? WIRE: 0; } else { int valid = 0; @@ -574,7 +571,6 @@ BL_Material* ConvertMaterial( material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0; material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0; valid++; } } @@ -607,10 +603,6 @@ BL_Material* ConvertMaterial( material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; - - if(tface->transp&~TF_CLIP) - material->ras_mode |= TRANSP; - material->tile = tface->tile; material->mode = tface->mode; @@ -631,7 +623,15 @@ BL_Material* ConvertMaterial( material->tile = 0; } + // with ztransp enabled, enforce alpha blending mode + if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) + material->transp = TF_ALPHA; + // always zsort alpha + add + if(material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) { + material->ras_mode |= ALPHA; + material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; + } // get uv sets if(validmat) @@ -711,132 +711,54 @@ BL_Material* ConvertMaterial( } -static void BL_ComputeTriTangentSpace(const MT_Vector3 &v1, const MT_Vector3 &v2, const MT_Vector3 &v3, - const MT_Vector2 &uv1, const MT_Vector2 &uv2, const MT_Vector2 &uv3, - MFace* mface, MT_Vector3 *tan1, MT_Vector3 *tan2) -{ - MT_Vector3 dx1(v2 - v1), dx2(v3 - v1); - MT_Vector2 duv1(uv2 - uv1), duv2(uv3 - uv1); - - MT_Scalar r = 1.0 / (duv1.x() * duv2.y() - duv2.x() * duv1.y()); - duv1 *= r; - duv2 *= r; - MT_Vector3 sdir(duv2.y() * dx1 - duv1.y() * dx2); - MT_Vector3 tdir(duv1.x() * dx2 - duv2.x() * dx1); - - tan1[mface->v1] += sdir; - tan1[mface->v2] += sdir; - tan1[mface->v3] += sdir; - - tan2[mface->v1] += tdir; - tan2[mface->v2] += tdir; - tan2[mface->v3] += tdir; -} - -static MT_Vector4* BL_ComputeMeshTangentSpace(Mesh* mesh) -{ - MFace* mface = static_cast<MFace*>(mesh->mface); - MTFace* tface = static_cast<MTFace*>(mesh->mtface); - - MT_Vector3 *tan1 = new MT_Vector3[mesh->totvert]; - MT_Vector3 *tan2 = new MT_Vector3[mesh->totvert]; - - int v; - for (v = 0; v < mesh->totvert; v++) - { - tan1[v] = MT_Vector3(0.0, 0.0, 0.0); - tan2[v] = MT_Vector3(0.0, 0.0, 0.0); - } - - for (int p = 0; p < mesh->totface; p++, mface++, tface++) - { - MT_Vector3 v1(mesh->mvert[mface->v1].co), - v2(mesh->mvert[mface->v2].co), - v3(mesh->mvert[mface->v3].co); - - MT_Vector2 uv1(tface->uv[0]), - uv2(tface->uv[1]), - uv3(tface->uv[2]); - - BL_ComputeTriTangentSpace(v1, v2, v3, uv1, uv2, uv3, mface, tan1, tan2); - if (mface->v4) - { - MT_Vector3 v4(mesh->mvert[mface->v4].co); - MT_Vector2 uv4(tface->uv[3]); - - BL_ComputeTriTangentSpace(v1, v3, v4, uv1, uv3, uv4, mface, tan1, tan2); - } - } - - MT_Vector4 *tangent = new MT_Vector4[mesh->totvert]; - for (v = 0; v < mesh->totvert; v++) - { - const MT_Vector3 no(mesh->mvert[v].no[0]/32767.0, - mesh->mvert[v].no[1]/32767.0, - mesh->mvert[v].no[2]/32767.0); - // Gram-Schmidt orthogonalize - MT_Vector3 t(tan1[v] - no.cross(no.cross(tan1[v]))); - if (!MT_fuzzyZero(t)) - t /= t.length(); - - tangent[v].x() = t.x(); - tangent[v].y() = t.y(); - tangent[v].z() = t.z(); - // Calculate handedness - tangent[v].w() = no.dot(tan1[v].cross(tan2[v])) < 0.0 ? -1.0 : 1.0; - } - - delete [] tan1; - delete [] tan2; - - return tangent; -} - RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; - bool skinMesh = false; - + bool skinMesh = false; int lightlayer = blenderobj->lay; - - MFace* mface = static_cast<MFace*>(mesh->mface); - MTFace* tface = static_cast<MTFace*>(mesh->mtface); + + // Get DerivedMesh data + DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); + + MVert *mvert = dm->getVertArray(dm); + int totvert = dm->getNumVerts(dm); + + MFace *mface = dm->getFaceArray(dm); + MTFace *tface = static_cast<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE)); + MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL)); + float (*tangent)[3] = NULL; + int totface = dm->getNumFaces(dm); const char *tfaceName = ""; - MCol* mmcol = mesh->mcol; - MT_assert(mface || mesh->totface == 0); + if(tface) { + DM_add_tangent_layer(dm); + tangent = (float(*)[3])dm->getFaceDataArray(dm, CD_TANGENT); + } // Determine if we need to make a skinned mesh - if (mesh->dvert || mesh->key){ + if (mesh->dvert || mesh->key) { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } - else { + else meshobj = new RAS_MeshObject(mesh, lightlayer); - } - MT_Vector4 *tangent = 0; - if (tface) - tangent = BL_ComputeMeshTangentSpace(mesh); - // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; - for (int lay=0; lay<MAX_MTFACE; lay++) - { + for (int lay=0; lay<MAX_MTFACE; lay++) { layers[lay].face = 0; layers[lay].name = ""; } - int validLayers = 0; - for (int i=0; i<mesh->fdata.totlayer; i++) + for (int i=0; i<dm->faceData.totlayer; i++) { - if (mesh->fdata.layers[i].type == CD_MTFACE) + if (dm->faceData.layers[i].type == CD_MTFACE) { assert(validLayers <= 8); - layers[validLayers].face = (MTFace*)mesh->fdata.layers[i].data;; - layers[validLayers].name = mesh->fdata.layers[i].name; + layers[validLayers].face = (MTFace*)(dm->faceData.layers[i].data); + layers[validLayers].name = dm->faceData.layers[i].name; if(tface == layers[validLayers].face) tfaceName = layers[validLayers].name; validLayers++; @@ -844,271 +766,269 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert); - for (int f=0;f<mesh->totface;f++,mface++) + meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + + for (int f=0;f<totface;f++,mface++) { - + Material* ma = 0; bool collider = true; - - // only add valid polygons - if (mface->v3) - { - MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); - MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); - // rgb3 is set from the adjoint face in a square - unsigned int rgb0,rgb1,rgb2,rgb3 = 0; - MT_Vector3 no0(mesh->mvert[mface->v1].no[0], mesh->mvert[mface->v1].no[1], mesh->mvert[mface->v1].no[2]), - no1(mesh->mvert[mface->v2].no[0], mesh->mvert[mface->v2].no[1], mesh->mvert[mface->v2].no[2]), - no2(mesh->mvert[mface->v3].no[0], mesh->mvert[mface->v3].no[1], mesh->mvert[mface->v3].no[2]), - no3(0.0, 0.0, 0.0); - MT_Point3 pt0(mesh->mvert[mface->v1].co), - pt1(mesh->mvert[mface->v2].co), - pt2(mesh->mvert[mface->v3].co), - pt3(0.0, 0.0, 0.0); - MT_Vector4 tan0(0.0, 0.0, 0.0, 0.0), - tan1(0.0, 0.0, 0.0, 0.0), - tan2(0.0, 0.0, 0.0, 0.0), - tan3(0.0, 0.0, 0.0, 0.0); - - no0 /= 32767.0; - no1 /= 32767.0; - no2 /= 32767.0; - if (mface->v4) - { - pt3 = MT_Point3(mesh->mvert[mface->v4].co); - no3 = MT_Vector3(mesh->mvert[mface->v4].no[0], mesh->mvert[mface->v4].no[1], mesh->mvert[mface->v4].no[2]); - no3 /= 32767.0; + MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); + MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); + unsigned int rgb0,rgb1,rgb2,rgb3 = 0; + + MT_Vector3 no0, no1, no2, no3; + MT_Point3 pt0, pt1, pt2, pt3; + MT_Vector4 tan0, tan1, tan2, tan3; + + /* get coordinates, normals and tangents */ + pt0 = MT_Point3(mvert[mface->v1].co); + pt1 = MT_Point3(mvert[mface->v2].co); + pt2 = MT_Point3(mvert[mface->v3].co); + pt3 = (mface->v4)? MT_Point3(mvert[mface->v4].co): MT_Point3(0.0, 0.0, 0.0); + + if(mface->flag & ME_SMOOTH) { + float n0[3], n1[3], n2[3], n3[3]; + + NormalShortToFloat(n0, mvert[mface->v1].no); + NormalShortToFloat(n1, mvert[mface->v2].no); + NormalShortToFloat(n2, mvert[mface->v3].no); + no0 = n0; + no1 = n1; + no2 = n2; + + if(mface->v4) { + NormalShortToFloat(n3, mvert[mface->v4].no); + no3 = n3; } + else + no3 = MT_Vector3(0.0, 0.0, 0.0); + } + else { + float fno[3]; + + if(mface->v4) + CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, mvert[mface->v4].co, fno); + else + CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, fno); + + no0 = no1 = no2 = no3 = MT_Vector3(fno); + } + + if(tangent) { + tan0 = tangent[f*4 + 0]; + tan1 = tangent[f*4 + 1]; + tan2 = tangent[f*4 + 2]; + + if (mface->v4) + tan3 = tangent[f*4 + 3]; + } + + /* get material */ + ma = give_current_material(blenderobj, mface->mat_nr+1); - if(!(mface->flag & ME_SMOOTH)) - { - MT_Vector3 norm = ((pt1-pt0).cross(pt2-pt0)).safe_normalized(); - norm[0] = ((int) (10*norm[0]))/10.0; - norm[1] = ((int) (10*norm[1]))/10.0; - norm[2] = ((int) (10*norm[2]))/10.0; - no0=no1=no2=no3= norm; - + { + bool polyvisible = true; + RAS_IPolyMaterial* polymat = NULL; + BL_Material *bl_mat = NULL; + + if(converter->GetMaterials()) { + /* do Blender Multitexture and Blender GLSL materials */ + unsigned int rgb[4]; + MT_Point2 uv[4]; + + /* first is the BL_Material */ + bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol, + lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); + + bl_mat->material_index = (int)mface->mat_nr; + + polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + collider = ((bl_mat->ras_mode & COLLIDER)!=0); + + /* vertex colors and uv's were stored in bl_mat temporarily */ + bl_mat->GetConversionRGB(rgb); + rgb0 = rgb[0]; rgb1 = rgb[1]; + rgb2 = rgb[2]; rgb3 = rgb[3]; + + bl_mat->GetConversionUV(uv); + uv0 = uv[0]; uv1 = uv[1]; + uv2 = uv[2]; uv3 = uv[3]; + + bl_mat->GetConversionUV2(uv); + uv20 = uv[0]; uv21 = uv[1]; + uv22 = uv[2]; uv23 = uv[3]; + + /* then the KX_BlenderMaterial */ + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); } + else { + /* do Texture Face materials */ + Image* bima = (tface)? (Image*)tface->tpage: NULL; + STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - { - Material* ma = 0; - bool polyvisible = true; - RAS_IPolyMaterial* polymat = NULL; - BL_Material *bl_mat = NULL; - - if(converter->GetMaterials()) - { - if(mesh->totcol > 1) - ma = mesh->mat[mface->mat_nr]; - else - ma = give_current_material(blenderobj, 1); - - bl_mat = ConvertMaterial(mesh, ma, tface, tfaceName, mface, mmcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - // set the index were dealing with - bl_mat->material_index = (int)mface->mat_nr; - - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); - collider = ((bl_mat->ras_mode & COLLIDER)!=0); + char transp=0; + short mode=0, tile=0; + int tilexrep=4,tileyrep = 4; + + if (bima) { + tilexrep = bima->xrep; + tileyrep = bima->yrep; + } + + /* get tface properties if available */ + if(tface) { + /* TF_DYNAMIC means the polygon is a collision face */ + collider = ((tface->mode & TF_DYNAMIC) != 0); + transp = tface->transp; + tile = tface->tile; + mode = tface->mode; - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); - unsigned int rgb[4]; - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; - MT_Point2 uv[4]; - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; - - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; - - if(tangent){ - tan0 = tangent[mface->v1]; - tan1 = tangent[mface->v2]; - tan2 = tangent[mface->v3]; - if (mface->v4) - tan3 = tangent[mface->v4]; - } + uv0 = MT_Point2(tface->uv[0]); + uv1 = MT_Point2(tface->uv[1]); + uv2 = MT_Point2(tface->uv[2]); + + if (mface->v4) + uv3 = MT_Point2(tface->uv[3]); + } + else { + /* no texfaces, set COLLSION true and everything else FALSE */ + mode = default_face_mode; + transp = TF_SOLID; + tile = 0; } - else - { - ma = give_current_material(blenderobj, 1); - Image* bima = ((mesh->mtface && tface) ? (Image*) tface->tpage : NULL); - - STR_String imastr = - ((mesh->mtface && tface) ? - (bima? (bima)->id.name : "" ) : "" ); - - char transp=0; - short mode=0, tile=0; - int tilexrep=4,tileyrep = 4; + /* get vertex colors */ + if (mcol) { + /* we have vertex colors */ + rgb0 = KX_Mcol2uint_new(mcol[0]); + rgb1 = KX_Mcol2uint_new(mcol[1]); + rgb2 = KX_Mcol2uint_new(mcol[2]); - if (bima) - { - tilexrep = bima->xrep; - tileyrep = bima->yrep; - - } + if (mface->v4) + rgb3 = KX_Mcol2uint_new(mcol[3]); + } + else { + /* no vertex colors, take from material, otherwise white */ + unsigned int color = 0xFFFFFFFFL; - if (mesh->mtface && tface) + if (ma) { - // Use texface colors if available - //TF_DYNAMIC means the polygon is a collision face - collider = ((tface->mode & TF_DYNAMIC) != 0); - transp = tface->transp &~ TF_CLIP; - tile = tface->tile; - mode = tface->mode; - - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; - uv0 = MT_Point2(tface->uv[0]); - uv1 = MT_Point2(tface->uv[1]); - uv2 = MT_Point2(tface->uv[2]); - - if (mface->v4) - uv3 = MT_Point2(tface->uv[3]); - } - else - { - // no texfaces, set COLLSION true and everything else FALSE + col_converter.cp[3] = (unsigned char) (ma->r*255.0); + col_converter.cp[2] = (unsigned char) (ma->g*255.0); + col_converter.cp[1] = (unsigned char) (ma->b*255.0); + col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); - mode = default_face_mode; - transp = TF_SOLID; - tile = 0; + color = col_converter.integer; } - if (mmcol) - { - // Use vertex colors - rgb0 = KX_Mcol2uint_new(mmcol[0]); - rgb1 = KX_Mcol2uint_new(mmcol[1]); - rgb2 = KX_Mcol2uint_new(mmcol[2]); - - if (mface->v4) - rgb3 = KX_Mcol2uint_new(mmcol[3]); - } - else { - // no vertex colors: take from material if we have one, - // otherwise set to white - unsigned int color = 0xFFFFFFFFL; + rgb0 = KX_rgbaint2uint_new(color); + rgb1 = KX_rgbaint2uint_new(color); + rgb2 = KX_rgbaint2uint_new(color); + + if (mface->v4) + rgb3 = KX_rgbaint2uint_new(color); + } + + bool istriangle = (mface->v4==0); - if (ma) - { - union - { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - - col_converter.cp[3] = (unsigned char) (ma->r*255.0); - col_converter.cp[2] = (unsigned char) (ma->g*255.0); - col_converter.cp[1] = (unsigned char) (ma->b*255.0); - col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); - - color = col_converter.integer; - } + // only zsort alpha + add + bool alpha = (transp == TF_ALPHA || transp == TF_ADD); + bool zsort = (mode & TF_ALPHASORT)? alpha: 0; + + polymat = new KX_PolygonMaterial(imastr, ma, + tile, tilexrep, tileyrep, + mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); - rgb0 = KX_rgbaint2uint_new(color); - rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(color); - } - - bool istriangle = (mface->v4==0); - bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; - - polymat = new KX_PolygonMaterial(imastr, ma, - tile, tilexrep, tileyrep, - mode, transp, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mmcol); - - if (ma) - { - polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; - polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 - polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + if (ma) { + polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; + polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 + polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + } + else { + polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); + polymat->m_shininess = 35.0; + } + } - } else - { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.0; - } + // see if a bucket was reused or a new one was created + // this way only one KX_BlenderMaterial object has to exist per bucket + bool bucketCreated; + RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); + if (bucketCreated) { + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); + if(converter->GetMaterials()) { + converter->RegisterBlenderMaterial(bl_mat); } - - // see if a bucket was reused or a new one was created - // this way only one KX_BlenderMaterial object has to exist per bucket - bool bucketCreated; - RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); - if (bucketCreated) { - // this is needed to free up memory afterwards - converter->RegisterPolyMaterial(polymat); - if(converter->GetMaterials()) { - converter->RegisterBlenderMaterial(bl_mat); - } - } else { - // delete the material objects since they are no longer needed - // from now on, use the polygon material from the material bucket - delete polymat; - if(converter->GetMaterials()) { - delete bl_mat; - } - polymat = bucket->GetPolyMaterial(); + } else { + // delete the material objects since they are no longer needed + // from now on, use the polygon material from the material bucket + delete polymat; + if(converter->GetMaterials()) { + delete bl_mat; } - - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + polymat = bucket->GetPolyMaterial(); + } + + int nverts = mface->v4?4:3; + int vtxarray = meshobj->FindVertexArray(nverts,polymat); + RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - bool flat; + bool flat; - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else + if (skinMesh) { + /* If the face is set to solid, all fnors are the same */ + if (mface->flag & ME_SMOOTH) flat = false; + else + flat = true; + } + else + flat = false; - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); + if (nverts==4) + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - meshobj->AddPolygon(poly); - if (poly->IsCollider()) + meshobj->AddPolygon(poly); + if (poly->IsCollider()) + { + RAS_TriangleIndex idx; + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v2; + idx.m_index[2] = mface->v3; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + if (nverts==4) { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v3; + idx.m_index[2] = mface->v4; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); } - -// poly->SetVisibleWireframeEdges(mface->edcode); - poly->SetCollider(collider); } + +// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetCollider(collider); } + if (tface) tface++; - if (mmcol) - mmcol+=4; + if (mcol) + mcol+=4; for (int lay=0; lay<MAX_MTFACE; lay++) { @@ -1127,11 +1047,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* (*mit)->GetPolyMaterial()->OnConstruction(); } - if(tangent) - delete [] tangent; - if (layers) delete []layers; + + dm->release(dm); return meshobj; } @@ -1819,7 +1738,7 @@ KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){ return 0; } -#include "BLI_arithb.h" + // convert blender objects into ketsji gameobjects void BL_ConvertBlenderObjects(struct Main* maggie, const STR_String& scenename, diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index dd45d522b9f..a9a0771936c 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -1,6 +1,10 @@ #include "DNA_customdata_types.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_main.h" #include "BL_BlenderShader.h" #include "BL_Material.h" @@ -10,30 +14,51 @@ #include "GPU_material.h" #endif +#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" + + /* this is evil, but we need the scene to create materials with + * lights from the correct scene .. */ +static struct Scene *GetSceneForName(const STR_String& scenename) +{ + Scene *sce; + + for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) + if (scenename == (sce->id.name+2)) + return sce; -const bool BL_BlenderShader::Ok()const + return (Scene*)G.main->scene.first; +} + +bool BL_BlenderShader::Ok() { #ifdef BLENDER_GLSL - return (mGPUMat != 0); + VerifyShader(); + + return (mMat && mMat->gpumaterial); #else return 0; #endif } -BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) +BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) : #ifdef BLENDER_GLSL - mGPUMat(0), + mScene(scene), + mMat(ma), + mGPUMat(NULL), #endif mBound(false), mLightLayer(lightlayer) { #ifdef BLENDER_GLSL - if(ma) { - GPU_material_from_blender(ma); - mGPUMat = ma->gpumaterial; + mBlenderScene = GetSceneForName(scene->GetName()); + mBlendMode = GPU_BLEND_SOLID; + + if(mMat) { + GPU_material_from_blender(mBlenderScene, mMat); + mGPUMat = mMat->gpumaterial; } #endif } @@ -41,17 +66,29 @@ BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) BL_BlenderShader::~BL_BlenderShader() { #ifdef BLENDER_GLSL - if(mGPUMat) { - GPU_material_unbind(mGPUMat); - mGPUMat = 0; - } + if(mMat && mMat->gpumaterial) + GPU_material_unbind(mMat->gpumaterial); +#endif +} + +bool BL_BlenderShader::VerifyShader() +{ +#ifdef BLENDER_GLSL + if(mMat && !mMat->gpumaterial) + GPU_material_from_blender(mBlenderScene, mMat); + + mGPUMat = mMat->gpumaterial; + + return (mMat && mGPUMat); +#else + return false; #endif } void BL_BlenderShader::SetProg(bool enable) { #ifdef BLENDER_GLSL - if(mGPUMat) { + if(VerifyShader()) { if(enable) { GPU_material_bind(mGPUMat, mLightLayer); mBound = true; @@ -70,7 +107,7 @@ int BL_BlenderShader::GetAttribNum() GPUVertexAttribs attribs; int i, enabled = 0; - if(!mGPUMat) + if(!VerifyShader()) return enabled; GPU_material_vertex_attributes(mGPUMat, &attribs); @@ -96,7 +133,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) ras->SetAttribNum(0); - if(!mGPUMat) + if(!VerifyShader()) return; if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { @@ -142,9 +179,11 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { #ifdef BLENDER_GLSL - float obmat[4][4], viewmat[4][4], viewinvmat[4][4]; + float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + + VerifyShader(); - if(!mGPUMat || !mBound) + if(!mGPUMat) // || !mBound) return; MT_Matrix4x4 model; @@ -158,10 +197,22 @@ void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) view.invert(); view.getValue((float*)viewinvmat); - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat); + if(ms.m_bObjectColor) + ms.m_RGBAcolor.getValue((float*)obcol); + else + obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; + + GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); + + mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); #endif } +int BL_BlenderShader::GetBlendMode() +{ + return mBlendMode; +} + bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { #ifdef BLENDER_GLSL diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index b758d1a9cba..da9765dafa4 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -14,7 +14,10 @@ #include "RAS_IPolygonMaterial.h" +#include "KX_Scene.h" + struct Material; +struct Scene; class BL_Material; #define BL_MAX_ATTRIB 16 @@ -27,21 +30,28 @@ class BL_BlenderShader { private: #ifdef BLENDER_GLSL + KX_Scene *mScene; + struct Scene *mBlenderScene; + struct Material *mMat; GPUMaterial *mGPUMat; #endif bool mBound; int mLightLayer; + int mBlendMode; + + bool VerifyShader(); public: - BL_BlenderShader(struct Material *ma, int lightlayer); + BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer); virtual ~BL_BlenderShader(); - const bool Ok()const; + bool Ok(); void SetProg(bool enable); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); }; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 568f7e171de..dcb66ea2579 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -129,8 +129,7 @@ enum BL_flag TEXALPHA=8, // use alpha combiner functions TEXNEG=16, // negate blending HASIPO=32, - USENEGALPHA=64, - ALPHA_TEST=128 + USENEGALPHA=64 }; // BL_Material::ras_mode @@ -139,7 +138,7 @@ enum BL_ras_mode POLY_VIS=1, COLLIDER=2, ZSORT=4, - TRANSP=8, + ALPHA=8, TRIANGLE=16, USE_LIGHT=32, WIRE=64 diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index f24ef4322f0..f0ef84032f7 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -384,8 +384,6 @@ void BL_Texture::DisableUnit() void BL_Texture::DisableAllTextures() { - glDisable(GL_BLEND); - for(int i=0; i<MAXTEX; i++) { if(GLEW_ARB_multitexture) glActiveTextureARB(GL_TEXTURE0_ARB+i); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 0f445a9f32e..a67e5b26667 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -38,6 +38,7 @@ extern "C" { // ------------------------------------ #define spit(x) std::cout << x << std::endl; +BL_Shader *KX_BlenderMaterial::mLastShader = NULL; BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; //static PyObject *gTextureDict = 0; @@ -58,7 +59,8 @@ KX_BlenderMaterial::KX_BlenderMaterial( data->tilexrep[0], data->tileyrep[0], data->mode, - ((data->ras_mode &TRANSP)!=0), + data->transp, + ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), lightlayer, ((data->ras_mode &TRIANGLE)!=0), @@ -79,7 +81,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( m_flag |=RAS_BLENDERMAT; m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; - m_flag |=(mMaterial->ras_mode &ALPHA_TEST)!=0?RAS_FORCEALPHA:0; // figure max int enabled = mMaterial->num_enabled; @@ -158,12 +159,29 @@ void KX_BlenderMaterial::OnConstruction() mConstructed = true; } +void KX_BlenderMaterial::EndFrame() +{ + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader = NULL; + } + + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader = NULL; + } +} + void KX_BlenderMaterial::OnExit() { if( mShader ) { - //note, the shader here is allocated, per unique material - //and this function is called per face - mShader->SetProg(false); + //note, the shader here is allocated, per unique material + //and this function is called per face + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + delete mShader; mShader = 0; } @@ -197,13 +215,19 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) int i; if( !enable || !mShader->Ok() ) { // frame cleanup. - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } BL_Texture::DisableAllTextures(); mShader->SetProg(true); + mLastShader = mShader; BL_Texture::ActivateFirst(); @@ -217,9 +241,12 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + // tested to be valid enums glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); @@ -234,11 +261,14 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { + ras->SetBlendingMode(mMaterial->transp); BL_Texture::DisableAllTextures(); if(mLastBlenderShader) @@ -251,17 +281,17 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) { - if(GLEW_ARB_shader_objects && mShader) - mShader->SetProg(false); - BL_Texture::DisableAllTextures(); - if( !enable ) + + if( !enable ) { + ras->SetBlendingMode(TF_SOLID); return; + } BL_Texture::ActivateFirst(); if( mMaterial->IdMode == DEFAULT_BLENDER ) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); return; } @@ -271,7 +301,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) mTextures[0].ActivateTexture(); mTextures[0].setTexEnv(0, true); mTextures[0].SetMapping(mMaterial->mapping[0].mapping); - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } return; } @@ -294,9 +324,12 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); } @@ -356,6 +389,11 @@ KX_BlenderMaterial::ActivateBlenderShaders( { KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + // reset... if(tmp->mMaterial->IsShared()) cachingInfo =0; @@ -402,6 +440,11 @@ KX_BlenderMaterial::ActivateMat( { KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; @@ -451,7 +494,10 @@ KX_BlenderMaterial::Activate( return dopass; } else { - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } mPass = 0; dopass = false; return dopass; @@ -499,10 +545,22 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const { - if(mShader && GLEW_ARB_shader_objects) + if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); - else if(mBlenderShader && GLEW_ARB_shader_objects) + } + else if(mBlenderShader && GLEW_ARB_shader_objects) { + int blendmode; + mBlenderShader->Update(ms, rasty); + + /* we do blend modes here, because they can change per object + * with the same material due to obcolor */ + blendmode = mBlenderShader->GetBlendMode(); + if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) + blendmode = mMaterial->transp; + + rasty->SetBlendingMode(blendmode); + } } void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const @@ -582,31 +640,6 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const ras->EnableTextures(false); } -bool KX_BlenderMaterial::setDefaultBlending() -{ - if( mMaterial->transp &TF_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_ALPHA ) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_CLIP ) { - glDisable(GL_BLEND); - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc(GL_GREATER, 0.5f); - return false; - } - return false; -} - void KX_BlenderMaterial::setTexMatrixData(int i) { glMatrixMode(GL_TEXTURE); @@ -831,12 +864,14 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") void KX_BlenderMaterial::SetBlenderGLSLShader(void) { if(!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mMaterial->material, m_lightlayer); + mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, m_lightlayer); if(!mBlenderShader->Ok()) { delete mBlenderShader; mBlenderShader = 0; } + else + m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index bf6d2095e7c..0d7657b8cdb 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -90,11 +90,13 @@ public: // -------------------------------- // pre calculate to avoid pops/lag at startup virtual void OnConstruction( ); + + static void EndFrame(); + private: BL_Material* mMaterial; BL_Shader* mShader; BL_BlenderShader* mBlenderShader; - static BL_BlenderShader *mLastBlenderShader; KX_Scene* mScene; BL_Texture mTextures[MAXTEX]; // texture array bool mUserDefBlend; @@ -114,7 +116,6 @@ private: void setBlenderShaderData( bool enable, RAS_IRasterizer *ras); void setShaderData( bool enable, RAS_IRasterizer *ras); - bool setDefaultBlending(); void setObjectMatrixData(int i, RAS_IRasterizer *ras); void setTexMatrixData(int i); @@ -123,6 +124,10 @@ private: // cleanup stuff void OnExit(); + // shader chacing + static BL_BlenderShader *mLastBlenderShader; + static BL_Shader *mLastShader; + mutable int mPass; }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 3d9c7aafd70..df478be5ca2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -77,10 +77,10 @@ KX_GameObject::KX_GameObject( SCA_IObject(T), m_bDyna(false), m_layer(0), + m_pBlenderObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), - m_pBlenderObject(NULL), m_bVisible(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), @@ -96,12 +96,9 @@ KX_GameObject::KX_GameObject( KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); m_pSGNode->SetParentRelation(parent_relation); - - }; - KX_GameObject::~KX_GameObject() { // is this delete somewhere ? @@ -165,6 +162,7 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; + }; // Set the name of the value @@ -454,12 +452,13 @@ KX_GameObject::UpdateMaterialData( ) { 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 ) + if(poly->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); @@ -467,7 +466,8 @@ KX_GameObject::UpdateMaterialData( { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) - SetObjectColor(rgba); + if(!(poly->GetFlag() & RAS_BLENDERGLSL)) + SetObjectColor(rgba); } else { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index db099d56b55..1d6cc975ab5 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -118,7 +118,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_bInitialized(false), m_activecam(0), m_bFixedTime(false), - m_game2ipo(false), m_firstframe(true), @@ -148,6 +147,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_showBackground(false), m_show_debug_properties(false), + m_game2ipo(false), + // Default behavior is to hide the cursor every frame. m_hideCursor(false), diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 93d6d5bb70d..144f74a1a4c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -59,7 +59,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -74,7 +75,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, tilexrep, tileyrep, mode, - transparant, + transp, + alpha, zsort, lightlayer, bIsTriangle, @@ -245,7 +247,7 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "drawingmode") return PyInt_FromLong(m_drawingmode); if (attr == "transparent") - return PyInt_FromLong(m_transparant); + return PyInt_FromLong(m_alpha); if (attr == "zsort") return PyInt_FromLong(m_zsort); if (attr == "lightlayer") @@ -312,7 +314,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) if (attr == "transparent") { - m_transparant = value; + m_alpha = value; return 0; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 19015494e06..11c8baa8b1f 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -64,7 +64,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 648a6ca31d5..ad476e492d0 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -37,6 +37,7 @@ #include "MT_assert.h" #include "KX_KetsjiEngine.h" +#include "KX_BlenderMaterial.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" #include "SCA_LogicManager.h" @@ -116,13 +117,13 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), + m_sceneConverter(NULL), m_physicsEnvironment(0), m_sceneName(sceneName), m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0), - m_sceneConverter(NULL) + m_ueberExecutionPriority(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -984,6 +985,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) //m_active_camera->Release(); m_active_camera = NULL; } + // in case this is a camera m_cameras.remove((KX_Camera*)newobj); @@ -1240,14 +1242,10 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi if (visible) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t( cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); - + // this adds the vertices to the display list for (int m=0;m<nummeshes;m++) - { - // this adds the vertices to the display list - (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); - } + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } gameobj->MarkVisible(visible); } @@ -1304,12 +1302,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam if (vis) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t(cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); for (int m=0;m<nummeshes;m++) { // this adds the vertices to the display list - (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } // Visibility/ non-visibility are marked // elsewhere now. @@ -1422,7 +1419,7 @@ void KX_Scene::UpdateParents(double curtime) RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated) { - return m_bucketmanager->RAS_BucketManagerFindBucket(polymat, bucketCreated); + return m_bucketmanager->FindBucket(polymat, bucketCreated); } @@ -1432,10 +1429,9 @@ void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, class RAS_IRenderTools* rendertools) { m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools); + KX_BlenderMaterial::EndFrame(); } - - void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index b4492ca03a9..82bdce44519 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -94,7 +94,6 @@ void RAS_BucketManager::RenderAlphaBuckets( const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - (*bit)->ClearScheduledPolygons(); for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { if ((*mit).m_bVisible) @@ -133,28 +132,15 @@ void RAS_BucketManager::Renderbuckets( rasty->ClearCachingInfo(); RAS_MaterialBucket::StartFrame(); - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - (*bucket)->ClearScheduledPolygons(); - } for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - RAS_IPolyMaterial *tmp = (*bucket)->GetPolyMaterial(); - if(tmp->IsZSort() || tmp->GetFlag() &RAS_FORCEALPHA ) - rasty->SetAlphaTest(true); - else - rasty->SetAlphaTest(false); - (*bucket)->Render(cameratrans,rasty,rendertools); - } - rasty->SetAlphaTest(false); RenderAlphaBuckets(cameratrans, rasty, rendertools); RAS_MaterialBucket::EndFrame(); } -RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) +RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { bucketCreated = false; BucketList::iterator it; @@ -172,7 +158,7 @@ RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMate RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; - if (bucket->IsTransparant()) + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else m_MaterialBuckets.push_back(bucket); @@ -195,3 +181,28 @@ void RAS_BucketManager::RAS_BucketManagerClearAll() m_MaterialBuckets.clear(); m_AlphaBuckets.clear(); } + +void RAS_BucketManager::ReleaseDisplayLists() +{ + BucketList::iterator bit; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } + + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } +} + diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 010478b1d5b..08b67ed022f 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -58,8 +58,9 @@ public: RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - RAS_MaterialBucket* RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + void ReleaseDisplayLists(); private: void RAS_BucketManagerClearAll(); diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 31bdd8638c2..4ee06d96603 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -39,7 +39,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -51,7 +52,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_tilexrep(tilexrep), m_tileyrep(tileyrep), m_drawingmode (mode), - m_transparant(transparant), + m_transp(transp), + m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), m_bIsTriangle(bIsTriangle), @@ -74,6 +76,7 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && + this->m_transp == lhs.m_transp && this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() @@ -85,7 +88,8 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_tile == lhs.m_tile && this->m_tilexrep == lhs.m_tilexrep && this->m_tileyrep == lhs.m_tileyrep && - this->m_transparant == lhs.m_transparant && + this->m_transp == lhs.m_transp && + this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && this->m_bIsTriangle == lhs.m_bIsTriangle && @@ -109,9 +113,9 @@ int RAS_IPolyMaterial::GetLightLayer() const return m_lightlayer; } -bool RAS_IPolyMaterial::IsTransparant() const +bool RAS_IPolyMaterial::IsAlpha() const { - return m_transparant; + return m_alpha || m_zsort; } bool RAS_IPolyMaterial::IsZSort() const diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 6d90d260a23..8fc53e6b038 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -52,7 +52,7 @@ enum MaterialProps RAS_AUTOGEN =128, RAS_NORMAL =256, RAS_DEFMULTI =512, - RAS_FORCEALPHA =1024 + RAS_BLENDERGLSL =1024 }; /** @@ -67,7 +67,8 @@ protected: int m_tile; int m_tilexrep,m_tileyrep; int m_drawingmode; // tface->mode - bool m_transparant; + int m_transp; + bool m_alpha; bool m_zsort; int m_lightlayer; bool m_bIsTriangle; @@ -102,7 +103,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -132,7 +134,7 @@ public: virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; - bool IsTransparant() const; + bool IsAlpha() const; bool IsZSort() const; bool UsesTriangles() const; unsigned int hash() const; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d4a9177a85d..9e03212283e 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -372,10 +372,6 @@ public: virtual void SetAmbientColor(float red, float green, float blue)=0; virtual void SetAmbient(float factor)=0; - /** - * Sets alpha testing - */ - virtual void SetAlphaTest(bool enable)=0; /** * Sets a polygon offset. z depth will be: z1 = mult*z0 + add @@ -398,8 +394,10 @@ public: virtual void DisableMotionBlur()=0; virtual float GetMotionBlurValue()=0; - virtual int GetMotionBlurState()=0; - virtual void SetMotionBlurState(int newstate)=0; + virtual int GetMotionBlurState()=0; + virtual void SetMotionBlurState(int newstate)=0; + + virtual void SetBlendingMode(int blendmode)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index e295d69e48e..0015b6a251f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -76,26 +76,11 @@ KX_MeshSlot::~KX_MeshSlot() RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) :m_bModified(true) { - m_bScheduled=true; m_material = mat; } -void RAS_MaterialBucket::SchedulePolygons(int drawingmode) -{ - m_bScheduled = true; -} - - - -void RAS_MaterialBucket::ClearScheduledPolygons() -{ - m_bScheduled = false; -} - - - RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; @@ -134,9 +119,14 @@ void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, (*it).m_RGBAcolor= rgbavec; } -bool RAS_MaterialBucket::IsTransparant() const +bool RAS_MaterialBucket::IsAlpha() const +{ + return (m_material->IsAlpha()); +} + +bool RAS_MaterialBucket::IsZSort() const { - return (m_material->IsTransparant()); + return (m_material->IsZSort()); } diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 13d8a53714a..4eef889c533 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -125,11 +125,9 @@ public: class RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - void SchedulePolygons(int drawingmode); - void ClearScheduledPolygons(); - RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsTransparant() const; + bool IsAlpha() const; + bool IsZSort() const; static void StartFrame(); static void EndFrame(); @@ -162,7 +160,6 @@ public: private: T_MeshSlotList m_meshSlots; - bool m_bScheduled; bool m_bModified; RAS_IPolyMaterial* m_material; double* m_pOGLMatrix; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 5087f62500e..9c0460aad2d 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -203,7 +203,6 @@ void RAS_MeshObject::DebugColor(unsigned int abgr) void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) { - RAS_TexVert* vertex = NULL; const vecVertexArray & vertexvec = GetVertexCache(mat); for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) @@ -220,22 +219,17 @@ void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, int numverts, RAS_IPolyMaterial* mat) { - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - //m_IndexArrayCount[idx.m_vtxarray] = indexpos + 3; - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); - if (!mat->UsesTriangles()) //if (!m_bUseTriangles) - { - //m_IndexArrayCount[idx.m_vtxarray] = indexpos+4; + + if (!mat->UsesTriangles()) ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); - } } - void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, int numverts, int edgecode, @@ -422,7 +416,6 @@ void RAS_MeshObject::Bucketize(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->SetMeshSlot(ms); } @@ -447,7 +440,6 @@ void RAS_MeshObject::MarkVisible(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); } @@ -466,7 +458,6 @@ void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, { RAS_MaterialBucket* bucket = *it; // RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); - bucket->SchedulePolygons(0); //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); bucket->RemoveMeshSlot(ms); } @@ -585,31 +576,36 @@ void RAS_MeshObject::UpdateMaterialList() struct RAS_MeshObject::polygonSlot { - float m_z; - RAS_Polygon *m_poly; - - polygonSlot(float z, RAS_Polygon* poly) : - m_z(z), - m_poly(poly) - {} - /** - * pnorm and pval form the plane equation that the distance from is used to - * sort against. - */ - polygonSlot(const MT_Vector3 &pnorm, const MT_Scalar &pval, RAS_MeshObject *mesh, RAS_Polygon* poly) : - m_poly(poly) + float m_z; + int m_index[4]; + + polygonSlot() {} + + /* pnorm is the normal from the plane equation that the distance from is + * used to sort again. */ + void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, + int offset, int nvert, const MT_Vector3& pnorm) { - const KX_VertexIndex &base = m_poly->GetIndexBase(); - RAS_TexVert *vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[0], poly->GetMaterial()->GetPolyMaterial()); - m_z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - - for(int i = 1; i < m_poly->VertexCount(); i++) - { - vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[i], poly->GetMaterial()->GetPolyMaterial()); - float z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - m_z += z; + MT_Vector3 center(0, 0, 0); + int i; + + for(i=0; i<nvert; i++) { + m_index[i] = indexarray[offset+i]; + center += vertexarray[m_index[i]].getLocalXYZ(); } - m_z /= m_poly->VertexCount(); + + /* note we don't divide center by the number of vertices, since all + * polygons have the same number of vertices, and that we leave out + * the 4-th component of the plane equation since it is constant. */ + m_z = MT_dot(pnorm, center); + } + + void set(KX_IndexArray& indexarray, int offset, int nvert) + { + int i; + + for(i=0; i<nvert; i++) + indexarray[offset+i] = m_index[i]; } }; @@ -629,100 +625,100 @@ struct RAS_MeshObject::fronttoback } }; - void RAS_MeshObject::SortPolygons(const MT_Transform &transform) { + // Limitations: sorting is quite simple, and handles many + // cases wrong, partially due to polygons being sorted per + // bucket. + // + // a) mixed triangles/quads are sorted wrong + // b) mixed materials are sorted wrong + // c) more than 65k faces are sorted wrong + // d) intersecting objects are sorted wrong + // e) intersecting polygons are sorted wrong + // + // a) can be solved by making all faces either triangles or quads + // if they need to be z-sorted. c) could be solved by allowing + // larger buckets, b) and d) cannot be solved easily if we want + // to avoid excessive state changes while drawing. e) would + // require splitting polygons. + if (!m_zsort) return; - + // Extract camera Z plane... const MT_Vector3 pnorm(transform.getBasis()[2]); - const MT_Scalar pval = transform.getOrigin()[2]; - - unsigned int numpolys = m_Polygons.size(); - std::multiset<polygonSlot, backtofront> alphapolyset; - std::multiset<polygonSlot, fronttoback> solidpolyset; - - for (unsigned int p = 0; p < numpolys; p++) - { - RAS_Polygon* poly = m_Polygons[p]; - if (poly->IsVisible()) - { - if (poly->GetMaterial()->GetPolyMaterial()->IsTransparant()) - { - alphapolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } else { - solidpolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } - } - } - - // Clear current array data. + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { - vector<KX_IndexArray*> *indexcache = &GetArrayOptimizer((*it)->GetPolyMaterial())->m_IndexArrayCache1; - for (vector<KX_IndexArray*>::iterator iit = indexcache->begin(); iit != indexcache->end(); ++iit) - (*iit)->clear(); - } + if(!(*it)->IsZSort()) + continue; - std::multiset<polygonSlot, fronttoback>::iterator sit = solidpolyset.begin(); - for (; sit != solidpolyset.end(); ++sit) - SchedulePoly((*sit).m_poly->GetVertexIndexBase(), (*sit).m_poly->VertexCount(), (*sit).m_poly->GetMaterial()->GetPolyMaterial()); - - std::multiset<polygonSlot, backtofront>::iterator ait = alphapolyset.begin(); - for (; ait != alphapolyset.end(); ++ait) - SchedulePoly((*ait).m_poly->GetVertexIndexBase(), (*ait).m_poly->VertexCount(), (*ait).m_poly->GetMaterial()->GetPolyMaterial()); + RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; + vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; + unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; + + for(i=0; i<indexarrays.size(); i++) { + KX_IndexArray& indexarray = *indexarrays[i]; + KX_VertexArray& vertexarray = *vertexarrays[i]; + + unsigned int totpoly = indexarray.size()/nvert; + vector<polygonSlot> slots(totpoly); + + /* get indices and z into temporary array */ + for(j=0; j<totpoly; j++) + slots[j].get(vertexarray, indexarray, j*nvert, nvert, pnorm); + + /* sort (stable_sort might be better, if flickering happens?) */ + sort(slots.begin(), slots.end(), backtofront()); + + /* get indices from temporary array again */ + for(j=0; j<totpoly; j++) + slots[j].set(indexarray, j*nvert, nvert); + } + } } -void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode) +void RAS_MeshObject::SchedulePolygons(int drawingmode) { -// int nummaterials = m_materials.size(); - int i; - if (m_bModified) { - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; + int i, numpolys = m_Polygons.size(); - bucket->SchedulePolygons(drawingmode); - if (bucket->GetPolyMaterial()->IsZSort()) + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + if ((*it)->IsZSort()) m_zsort = true; - } - - int numpolys = m_Polygons.size(); - if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) && - (drawingmode < RAS_IRasterizer::KX_SOLID)) + if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) { for (i=0;i<numpolys;i++) { RAS_Polygon* poly = m_Polygons[i]; if (poly->IsVisible()) - ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode() - ,poly->GetMaterial()->GetPolyMaterial()); + ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), + poly->GetMaterial()->GetPolyMaterial()); } m_zsort = false; } else { - if (!m_zsort) + for (i=0;i<numpolys;i++) { - for (i=0;i<numpolys;i++) - { - RAS_Polygon* poly = m_Polygons[i]; - if (poly->IsVisible()) - { - SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial()); - } - } + RAS_Polygon* poly = m_Polygons[i]; + if (poly->IsVisible()) + SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), + poly->GetMaterial()->GetPolyMaterial()); } } m_bModified = false; - m_MeshMod = true; } } + diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 44ad508d1e8..99806666fa6 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -137,6 +137,18 @@ class RAS_MeshObject struct backtofront; struct fronttoback; + void SchedulePoly( + const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat + ); + + void ScheduleWireframePoly( + const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat + ); protected: enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; @@ -196,10 +208,7 @@ public: */ void SortPolygons(const MT_Transform &transform); - void SchedulePolygons( - const MT_Transform &transform, - int drawingmode - ); + void SchedulePolygons(int drawingmode); void ClearArrayData(); @@ -216,19 +225,7 @@ public: int numverts, RAS_IPolyMaterial* polymat ); - - void SchedulePoly( - const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat - ); - void ScheduleWireframePoly( - const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat - ); // find (and share) or add vertices // for some speedup, only the last 20 added vertices are searched for equality diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index dcc36bf5a39..1dcc6e70934 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -67,6 +67,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), + m_last_blendmode(0), m_materialCachingInfo(0) { m_viewmatrix.Identity(); @@ -171,6 +172,8 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; + SetBlendingMode(0); + glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -189,18 +192,6 @@ void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) } -void RAS_OpenGLRasterizer::SetAlphaTest(bool enable) -{ - if (enable) - { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.6f); - } - else glDisable(GL_ALPHA_TEST); -} - - - void RAS_OpenGLRasterizer::SetAmbient(float factor) { float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; @@ -353,6 +344,8 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } + SetBlendingMode(0); + glShadeModel(GL_SMOOTH); m_2DCanvas->BeginFrame(); @@ -1389,3 +1382,34 @@ void RAS_OpenGLRasterizer::DisableMotionBlur() m_motionblur = 0; m_motionblurvalue = -1.0; } + +void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) +{ + if(blendmode == m_last_blendmode) + return; + + if(blendmode == 0) { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else if(blendmode == 1) { + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + else if(blendmode == 2) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0f); + } + else if(blendmode == 4) { + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + } + + m_last_blendmode = blendmode; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 0d54552db05..02056cce446 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -99,6 +99,7 @@ protected: TexCoGen m_attrib[RAS_MAX_ATTRIB]; int m_texco_num; int m_attrib_num; + int m_last_blendmode; /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; @@ -142,8 +143,6 @@ public: virtual void SetFocalLength(const float focallength); virtual float GetFocalLength(); - virtual void SetAlphaTest(bool enable); - virtual void SwapBuffers(); virtual void IndexPrimitives( const vecVertexArray& vertexarrays, @@ -282,8 +281,8 @@ public: virtual void EnableMotionBlur(float motionblurvalue); virtual void DisableMotionBlur(); virtual float GetMotionBlurValue(){return m_motionblurvalue;}; - virtual int GetMotionBlurState(){return m_motionblur;}; - virtual void SetMotionBlurState(int newstate) + virtual int GetMotionBlurState(){return m_motionblur;}; + virtual void SetMotionBlurState(int newstate) { if(newstate<0) m_motionblur = 0; @@ -292,6 +291,8 @@ public: else m_motionblur = newstate; }; + + virtual void SetBlendingMode(int blendmode); }; #endif //__RAS_OPENGLRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index 852c94def3f..b74cb9cfcac 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -37,24 +37,6 @@ #include "RAS_Polygon.h" -/* -RAS_TexVert* RAS_Polygon::GetVertex(int index) -{ - if (m_bucket) - return m_bucket->GetVertex(m_vertexindexbase.m_vtxarray, m_vertexindexbase.m_indexarray[index]); - else - return NULL; -} -*/ - -/*void RAS_Polygon::Bucketize(double* oglmatrix) -{ - //Transform(trans); - if (m_bucket) - m_bucket->AddPolygon(this,oglmatrix); -} -*/ - RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, bool visible, int numverts, |