diff options
44 files changed, 1112 insertions, 435 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index a94a45958de..ff19ece8f94 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -289,53 +289,6 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel): layout.prop(lay, "name") -class DATA_PT_texface(MeshButtonsPanel, Panel): - bl_label = "Texture Face" - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} - - @classmethod - def poll(cls, context): - obj = context.object - return (context.mode == 'EDIT_MESH') and obj and obj.type == 'MESH' - - def draw(self, context): - layout = self.layout - col = layout.column() - - me = context.mesh - - tf = me.faces.active_tface - - if tf: - if context.scene.render.engine != 'BLENDER_GAME': - col.label(text="Options only supported in Game Engine") - - split = layout.split() - col = split.column() - - col.prop(tf, "use_image") - col.prop(tf, "use_light") - col.prop(tf, "hide") - col.prop(tf, "use_collision") - - col.prop(tf, "use_blend_shared") - col.prop(tf, "use_twoside") - col.prop(tf, "use_object_color") - - col = split.column() - - col.prop(tf, "use_halo") - col.prop(tf, "use_billboard") - col.prop(tf, "use_shadow_cast") - col.prop(tf, "use_bitmap_text") - col.prop(tf, "use_alpha_sort") - - col = layout.column() - col.prop(tf, "blend_type") - else: - col.label(text="No UV Texture") - - class DATA_PT_vertex_colors(MeshButtonsPanel, Panel): bl_label = "Vertex Colors" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 13ce92f084c..68d7d5d4615 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -612,9 +612,37 @@ class MATERIAL_PT_flare(MaterialButtonsPanel, Panel): col.prop(halo, "flare_subflare_size", text="Subsize") -class MATERIAL_PT_physics(MaterialButtonsPanel, Panel): +class MATERIAL_PT_game_settings(MaterialButtonsPanel, bpy.types.Panel): + bl_label = "Game Settings" + COMPAT_ENGINES = {'BLENDER_GAME'} + + @classmethod + def poll(cls, context): + return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + game = context.material.game_settings # dont use node material + + row = layout.row() + row.prop(game, "back_culling") + row.prop(game, "invisible") + row.prop(game, "text") + + row = layout.row() + row.label(text="Alpha Blend:") + row.label(text="Face Orientation:") + row = layout.row() + row.prop(game,"alpha_blend",text="") + row.prop(game,"face_orientation",text="") + +class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel): bl_label = "Physics" COMPAT_ENGINES = {'BLENDER_GAME'} + + def draw_header(self, context): + game = context.material.game_settings + self.layout.prop(game, "physics", text="") @classmethod def poll(cls, context): @@ -622,6 +650,7 @@ class MATERIAL_PT_physics(MaterialButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.active = context.material.game_settings.physics phys = context.material.physics # dont use node material diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 7f5a5f231cf..debe82e7ab2 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -380,6 +380,7 @@ class INFO_MT_help(Menu): layout.operator("wm.console_toggle", icon='CONSOLE') layout.separator() layout.operator("anim.update_data_paths", text="FCurve/Driver Version fix", icon='HELP') + layout.operator("logic.texface_convert", text="TexFace to Material Convert", icon='GAME') layout.separator() layout.operator("wm.splash", icon='BLENDER') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 742240d53b5..333c00c3f2a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 259 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 0c31083a266..8181ad6421c 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -168,6 +168,9 @@ struct Image *copy_image(struct Image *ima); /* merge source into dest, and free source */ void BKE_image_merge(struct Image *dest, struct Image *source); +/* check if texture has alpha (depth=32) */ +int BKE_image_has_alpha(struct Image *image); + /* image_gen.c */ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4]); void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 85b6f8f78fb..b3d24c10ed7 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -42,6 +42,8 @@ struct Main; struct Material; struct ID; struct Object; +struct Mesh; +struct MTFace; /* materials */ @@ -50,6 +52,7 @@ void free_material(struct Material *sc); void test_object_materials(struct ID *id); void resize_object_material(struct Object *ob, const short totcol); void init_material(struct Material *ma); +struct Material *add_material_main(struct Main *main, const char *name); struct Material *add_material(const char *name); struct Material *copy_material(struct Material *ma); struct Material *localize_material(struct Material *ma); @@ -101,6 +104,9 @@ void clear_mat_mtex_copybuf(void); void copy_mat_mtex_copybuf(struct ID *id); void paste_mat_mtex_copybuf(struct ID *id); +/* handle backward compatibility for tface/materials called from doversion (fileload=1) or Help Menu (fileload=0) */ +int do_version_tface(struct Main *main, int fileload); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 1660ac29217..cac7da76e07 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -988,15 +988,12 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, EditFace *efa; DMVertexAttribs attribs= {{{0}}}; GPUVertexAttribs gattribs; - MTFace *tf; - int transp, new_transp, orig_transp, tfoffset; + int tfoffset; int i, b, matnr, new_matnr, dodraw, layer; dodraw = 0; matnr = -1; - transp = GPU_get_material_blend_mode(); - orig_transp = transp; layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; @@ -1040,19 +1037,6 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); } - if(tfoffset != -1) { - tf = (MTFace*)((char*)efa->data)+tfoffset; - new_transp = tf->transp; - - if(new_transp != transp) { - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - if(dodraw) { glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); if (!drawSmooth) { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 44359a142c9..e6a472827ad 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1063,15 +1063,12 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); int a, b, dodraw, matnr, new_matnr; - int transp, new_transp, orig_transp; int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); cdDM_update_normals_from_pbvh(dm); matnr = -1; dodraw = 0; - transp = GPU_get_material_blend_mode(); - orig_transp = transp; glShadeModel(GL_SMOOTH); @@ -1111,22 +1108,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo continue; } - if(tf) { - new_transp = tf[a].transp; - - if(new_transp != transp) { - glEnd(); - - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - - glBegin(GL_QUADS); - } - } - if(!smoothnormal) { if(nors) { glNormal3fv(nors[a]); @@ -1259,33 +1240,6 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo continue; } - if(tf) { - new_transp = tf[a].transp; - - if(new_transp != transp) { - numfaces = curface - start; - if( numfaces > 0 ) { - if( dodraw ) { - if( numdata != 0 ) { - GPU_buffer_unlock(buffer); - GPU_interleaved_attrib_setup(buffer,datatypes,numdata); - } - glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3); - if( numdata != 0 ) { - varray = GPU_buffer_lock_stream(buffer); - } - } - } - start = curface; - - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - if( numdata != 0 ) { offset = 0; if(attribs.totorco) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 883f67c3061..30da2e01011 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -326,7 +326,7 @@ static void layerSwap_tface(void *data, const int *corner_indices) static void layerDefault_tface(void *data, int count) { static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL, - 0, 0, TF_DYNAMIC, 0, 0}; + 0, 0, TF_DYNAMIC|TF_CONVERTED, 0, 0}; MTFace *tf = (MTFace*)data; int i; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 002cfdbf41a..d764826cd47 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2290,3 +2290,20 @@ void BKE_image_user_calc_frame(ImageUser *iuser, int cfra, int fieldnr) iuser->framenr= framenr; if(iuser->ok==0) iuser->ok= 1; } + +int BKE_image_has_alpha(struct Image *image) +{ + ImBuf *ibuf; + void *lock; + int depth; + + ibuf= BKE_image_acquire_ibuf(image, NULL, &lock); + depth = (ibuf?ibuf->depth:0); + BKE_image_release_ibuf(image, lock); + + if (depth == 32) + return 1; + else + return 0; +} + diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 2a9e786d139..956d7b01b3b 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -43,6 +43,9 @@ #include "DNA_curve_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_customdata_types.h" +#include "DNA_ID.h" #include "DNA_meta_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -56,6 +59,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_material.h" @@ -188,6 +192,10 @@ void init_material(Material *ma) ma->vol.ms_diff = 1.f; ma->vol.ms_intensity = 1.f; + ma->game.flag=0; + ma->game.alpha_blend=0; + ma->game.face_orientation=0; + ma->mode= MA_TRACEBLE|MA_SHADBUF|MA_SHADOW|MA_RAYBIAS|MA_TANGENT_STR|MA_ZTRANSP; ma->shade_flag= MA_APPROX_OCCLUSION; ma->preview = NULL; @@ -1468,3 +1476,480 @@ void paste_matcopybuf(Material *ma) ma->nodetree= ntreeCopyTree(matcopybuf.nodetree); } + + +/*********************** texface to material convert functions **********************/ +/* encode all the TF information into a single int */ +int encode_tfaceflag(MTFace *tf, int convertall) +{ + /* calculate the flag */ + int flag = tf->mode; + + /* options that change the material offline render */ + if (!convertall) { + flag &= ~TF_OBCOL; + } + + /* clean flags that are not being converted */ + flag &= ~TF_TEX; + flag &= ~TF_SHAREDVERT; + flag &= ~TF_SHAREDCOL; + flag &= ~TF_CONVERTED; + + /* light tface flag is ignored in GLSL mode */ + flag &= ~TF_LIGHT; + + /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */ + flag |= tf->transp << 15; + + /* increase 1 so flag 0 is different than no flag yet */ + return flag + 1; +} + +/* set the material options based in the tface flag */ +void decode_tfaceflag(Material *ma, int flag, int convertall) +{ + int alphablend; + GameSettings *game= &ma->game; + + /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ + flag -= 1; + + alphablend = flag >> 15; //encoded in the encode_tfaceflag function + (*game).flag = 0; + + /* General Material Options */ + if ((flag & TF_DYNAMIC)==0) (*game).flag |= GEMAT_NOPHYSICS; + + /* Material Offline Rendering Properties */ + if (convertall) { + if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR; + } + + /* Special Face Properties */ + if ((flag & TF_TWOSIDE)==0) (*game).flag |= GEMAT_BACKCULL; + if (flag & TF_INVISIBLE)(*game).flag |= GEMAT_INVISIBLE; + if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT; + + /* Face Orientation */ + if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO; + else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD; + else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW; + + /* Alpha Blend */ + if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT; + else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA; + else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD; + else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP; +} + +/* boolean check to see if the mesh needs a material */ +int check_tfaceneedmaterial(int flag) +{ + // check if the flags we have are not deprecated != than default material options + // also if only flags are visible and collision see if all objects using this mesh have this option in physics + + /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ + flag -=1; + + // deprecated flags + flag &= ~TF_OBCOL; + flag &= ~TF_SHAREDVERT; + flag &= ~TF_SHAREDCOL; + + /* light tface flag is ignored in GLSL mode */ + flag &= ~TF_LIGHT; + + // automatic detected if tex image has alpha + flag &= ~(TF_ALPHA << 15); + // automatic detected if using texture + flag &= ~TF_TEX; + + // settings for the default NoMaterial + if (flag == TF_DYNAMIC) + return 0; + + else + return 1; +} + +/* return number of digits of an integer */ +// XXX to be optmized or replaced by an equivalent blender internal function +int integer_getdigits(int number) +{ + int i=0; + if (number == 0) return 1; + + while (number != 0){ + number = (int)(number/10); + i++; + } + return i; +} + +void calculate_tface_materialname(char *matname, char *newname, int flag) +{ + // if flag has only light and collision and material matches those values + // you can do strcpy(name, mat_name); + // otherwise do: + int digits = integer_getdigits(flag); + /* clamp the old name, remove the MA prefix and add the .TF.flag suffix + e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */ + sprintf(newname, "%.*s.TF.%0*d", MAX_ID_NAME-(digits+5), matname, digits, flag); +} + +/* returns -1 if no match */ +int mesh_getmaterialnumber(Mesh *me, Material *ma) { + int a; + + for (a=0; a<me->totcol; a++) + if (me->mat[a] == ma) + return a; + + return -1; +} + +/* append material */ +int mesh_addmaterial(Mesh *me, Material *ma) +{ + material_append_id(&me->id, NULL); + me->mat[me->totcol-1]= ma; + + id_us_plus(&ma->id); + + return me->totcol-1; +} + +Material *materialbyname(Main *main, char *name) +{ + Material *mat = NULL; + for (mat=main->mat.first;mat;mat=mat->id.next) { + if (strcmp(mat->id.name, name)==0) + return mat; + } + return NULL; +} + +void set_facetexture_flags(Material *ma, Image *image) +{ + if(image) { + ma->mode |= MA_FACETEXTURE; + /* we could check if the texture has alpha, but then more meshes sharing the same + * material may need it. Let's make it simple. */ + if(BKE_image_has_alpha(image)) + ma->mode |= MA_FACETEXTURE_ALPHA; + } +} + +/* returns material number */ +int convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) +{ + Material *ma; + char name[MAX_ID_NAME]; + int mat_nr= -1; + + /* new material, the name uses the flag*/ + sprintf(name, "MAMaterial.TF.%0*d", integer_getdigits(flag), flag); + + if ((ma=materialbyname(main, name))) { + mat_nr = mesh_getmaterialnumber(me, ma); + /* assign the material to the mesh */ + if(mat_nr == -1) mat_nr= mesh_addmaterial(me, ma); + + /* if needed set "Face Textures [Alpha]" Material options */ + set_facetexture_flags(ma, tf->tpage); + } + /* create a new material */ + else { + ma=add_material(name+2); + + if(ma){ + printf("TexFace Convert: Material \"%s\" created.\n", name+2); + mat_nr= mesh_addmaterial(me, ma); + + /* if needed set "Face Textures [Alpha]" Material options */ + set_facetexture_flags(ma, tf->tpage); + + decode_tfaceflag(ma, flag, 1); + // the final decoding will happen after, outside the main loop + // for now store the flag into the material and change light/tex/collision + // store the flag as a negative number + ma->game.flag = -flag; + id_us_min((ID *)ma); + } + else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", name+2, me->id.name+2); + } + + /* set as converted, no need to go bad to this face */ + tf->mode |= TF_CONVERTED; + return mat_nr; +} + +/* Function to fully convert materials */ +void convert_tfacematerial(Main *main, Material *ma) +{ + Mesh *me; + Material *mat_new; + MFace *mf; + MTFace *tf; + int flag, index; + int a, mat_nr; + CustomDataLayer *cdl; + char name[MAX_ID_NAME]; + + for(me=main->mesh.first; me; me=me->id.next){ + /* check if this mesh uses this material */ + for(a=0;a<me->totcol;a++) + if(me->mat[a] == ma) break; + + /* no material found */ + if (a == me->totcol) continue; + + /* get the active tface layer */ + index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); + cdl= (index == -1)? NULL: &me->fdata.layers[index]; + if (!cdl) continue; + + /* loop over all the faces and stop at the ones that use the material*/ + for(a=0, mf=me->mface; a<me->totface; a++, mf++) { + if(me->mat[(int)mf->mat_nr] != ma) continue; + + /* texface data for this face */ + tf = ((MTFace*)cdl->data) + a; + flag = encode_tfaceflag(tf, 1); + + /* the name of the new material */ + calculate_tface_materialname(ma->id.name, (char *)&name, flag); + + if ((mat_new=materialbyname(main, name))) { + /* material already existent, see if the mesh has it */ + mat_nr = mesh_getmaterialnumber(me, mat_new); + /* material is not in the mesh, add it */ + if(mat_nr == -1) mat_nr= mesh_addmaterial(me, mat_new); + } + /* create a new material */ + else { + mat_new=copy_material(ma); + if(mat_new){ + /* rename the material*/ + strcpy(mat_new->id.name, name); + id_us_min((ID *)mat_new); + + mat_nr= mesh_addmaterial(me, mat_new); + decode_tfaceflag(mat_new, flag, 1); + } + else { + printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", name+2, me->id.name+2); + mat_nr = mf->mat_nr; + continue; + } + } + + /* if the material has a texture but no texture channel + * set "Face Textures [Alpha]" Material options + * actually we need to run it always, because of old behavior + * of using face texture if any texture channel was present (multitex) */ + //if((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex)) + set_facetexture_flags(mat_new, tf->tpage); + + /* set the material number to the face*/ + mf->mat_nr = mat_nr; + } + /* remove material from mesh */ + for(a=0;a<me->totcol;) + if(me->mat[a] == ma) material_pop_id(&me->id, a, 1);else a++; + } +} + +int do_version_tface(Main *main, int fileload) +{ + Mesh *me; + Material *ma; + MFace *mf; + MTFace *tf; + CustomDataLayer *cdl; + int a; + int flag; + int index; + int nummat; + + /* sometimes mesh has no materials but will need a new one. In those + * cases we need to ignore the mf->mat_nr and only look at the face + * mode because it can be zero as unitialized or the 1st created material + */ + int nomaterialslots; + + /* alert to user to check the console */ + int nowarning = 1; + + /* mark all the materials to convertion with a flag + * if there is tface create a complete flag for that storing in flag + * if there is tface and flag > 0: creates a new flag based on this face + * if flags are different set flag to -1 + */ + + /* 1st part: marking mesh materials to update */ + for(me=main->mesh.first; me; me=me->id.next){ + if (me->id.lib) continue; + + /* get the active tface layer */ + index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); + cdl= (index == -1)? NULL: &me->fdata.layers[index]; + if (!cdl) continue; + + nomaterialslots = (me->totcol==0?1:0); + + /* loop over all the faces*/ + for(a=0, mf=me->mface; a<me->totface; a++, mf++) { + /* texface data for this face */ + tf = ((MTFace*)cdl->data) + a; + + /* conversion should happen only once */ + if (fileload) + tf->mode &= ~TF_CONVERTED; + else { + if((tf->mode & TF_CONVERTED)) continue; + else tf->mode |= TF_CONVERTED; + } + + /* no material slots */ + if(nomaterialslots) { + flag = encode_tfaceflag(tf, 1); + + /* create/find a new material and assign to the face */ + if (check_tfaceneedmaterial(flag)) + mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag); + + /* else mark them as no-material to be reverted to 0 later */ + else + mf->mat_nr = -1; + } + else if(mf->mat_nr < me->totcol) { + ma= me->mat[(int)mf->mat_nr]; + + /* no material create one if necessary */ + if(!ma) { + /* find a new material and assign to the face */ + flag = encode_tfaceflag(tf, 1); + + /* create/find a new material and assign to the face */ + if (check_tfaceneedmaterial(flag)) + mf->mat_nr= convert_tfacenomaterial(main, me, tf, flag); + + continue; + } + + /* we can't read from this if it comes from a library, + * at doversion time: direct_link might not have happened on it, + * so ma->mtex is not pointing to valid memory yet. + * later we could, but it's better not */ + else if(ma->id.lib) + continue; + + /* material already marked as disputed */ + else if(ma->game.flag == -99999) + continue; + + /* found a material */ + else { + flag = encode_tfaceflag(tf, ((fileload)?0:1)); + + /* first time changing this material */ + if (ma->game.flag == 0) + ma->game.flag= -flag; + + /* mark material as disputed */ + else if (ma->game.flag != -flag) { + ma->game.flag = -99999; + continue; + } + + /* material ok so far */ + else { + ma->game.flag = -flag; + + /* some people uses multitexture with TexFace by creating a texture + * channel which not necessarly the tf->tpage image. But the game engine + * was enabling it. Now it's required to set "Face Texture [Alpha] in the + * material settings. */ + if(!fileload) + set_facetexture_flags(ma, tf->tpage); + } + } + } + else + continue; + } + + /* if we didn't have material slot and now we do, we need to + * make sure the materials are correct */ + if(nomaterialslots) { + if (me->totcol>0) { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) { + if (mf->mat_nr == -1) { + /* texface data for this face */ + tf = ((MTFace*)cdl->data) + a; + mf->mat_nr= convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1)); + } + } + } else { + for(a=0, mf=me->mface; a<me->totface; a++, mf++) + mf->mat_nr=0; + } + } + + } + + /* 2nd part - conversion */ + /* skip library files */ + + /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */ + for (ma= main->mat.first, a=0; ma; ma= ma->id.next, a++) { + if (ma->id.lib) continue; + + /* disputed material */ + if (ma->game.flag == -99999) { + ma->game.flag = 0; + if (fileload) { + printf("Warning: material \"%s\" skipped - to convert old game texface to material go to the Help menu.\n", ma->id.name+2); + nowarning = 0; + } + else + convert_tfacematerial(main, ma); + continue; + } + + /* no conflicts in this material - 90% of cases + * convert from tface system to material */ + else if (ma->game.flag < 0){ + decode_tfaceflag(ma, -(ma->game.flag), 1); + + /* material is good make sure all faces using + * this material are set to converted */ + if (fileload) { + for(me=main->mesh.first; me; me=me->id.next){ + /* check if this mesh uses this material */ + for(a=0;a<me->totcol;a++) + if(me->mat[a] == ma) break; + + /* no material found */ + if (a == me->totcol) continue; + + /* get the active tface layer */ + index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); + cdl= (index == -1)? NULL: &me->fdata.layers[index]; + if (!cdl) continue; + + /* loop over all the faces and stop at the ones that use the material*/ + for(a=0, mf=me->mface; a<me->totface; a++, mf++) { + if(me->mat[(int)mf->mat_nr] != ma) continue; + else tf->mode |= TF_CONVERTED; + } + } + } + } + } + + return nowarning; +} + diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 2ff555b5b22..44242507616 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1378,7 +1378,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v int gridSize = ccgSubSurf_getGridSize(ss); int gridFaces = gridSize - 1; int edgeSize = ccgSubSurf_getEdgeSize(ss); - int transp, orig_transp, new_transp; char *faceFlags = ccgdm->faceFlags; int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; @@ -1386,8 +1385,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v doDraw = 0; matnr = -1; - transp = GPU_get_material_blend_mode(); - orig_transp = transp; #define PASSATTRIB(dx, dy, vert) { \ if(attribs.totorco) { \ @@ -1439,18 +1436,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, v continue; } - if(tf) { - new_transp = tf[i].transp; - - if(new_transp != transp) { - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); for (S=0; S<numVerts; S++) { DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 38454547f48..a5484d218d2 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -238,6 +238,7 @@ typedef struct OldNewMap { /* local prototypes */ static void *read_struct(FileData *fd, BHead *bh, const char *blockname); static void direct_link_modifiers(FileData *fd, ListBase *lb); +static void convert_tface_mt(FileData *fd, Main *main); static OldNewMap *oldnewmap_new(void) { @@ -3478,6 +3479,9 @@ static void lib_link_mesh(FileData *fd, Main *main) } me= me->id.next; } + + /* convert texface options to material */ + convert_tface_mt(fd, main); } static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts) @@ -7038,6 +7042,27 @@ static void do_versions_nodetree_dynamic_sockets(bNodeTree *ntree) sock->flag |= SOCK_DYNAMIC; } +void convert_tface_mt(FileData *fd, Main *main) +{ + Main *gmain; + + /* this is a delayed do_version (so it can create new materials) */ + if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 3)) { + + //XXX hack, material.c uses G.main all over the place, instead of main + // temporarily set G.main to the current main + gmain = G.main; + G.main = main; + + if(!(do_version_tface(main, 1))) { + BKE_report(fd->reports, RPT_ERROR, "Texface conversion problem. Error in console"); + } + + //XXX hack, material.c uses G.main allover the place, instead of main + G.main = gmain; + } +} + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index b256eeac4bc..8c035ca46fd 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -1473,10 +1473,8 @@ static void EM_mesh_copy_face(EditMesh *em, wmOperator *op, short type) tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if (tf_act->tpage) { tf->tpage = tf_act->tpage; - tf->mode |= TF_TEX; } else { tf->tpage = NULL; - tf->mode &= ~TF_TEX; } tf->tile= tf_act->tile; change = 1; @@ -1656,10 +1654,8 @@ void EM_mesh_copy_face_layer(EditMesh *em, wmOperator *op, short type) tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if (tf_from->tpage) { tf->tpage = tf_from->tpage; - tf->mode |= TF_TEX; } else { tf->tpage = NULL; - tf->mode &= ~TF_TEX; } tf->tile= tf_from->tile; change = 1; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index afab4ede229..e345caf1359 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -595,7 +595,7 @@ static void image_refresh(const bContext *C, ScrArea *UNUSED(sa)) tf = EM_get_active_mtface(em, NULL, NULL, 1); /* partially selected face is ok */ - if(tf && (tf->mode & TF_TEX)) { + if(tf) { /* don't need to check for pin here, see above */ sima->image= tf->tpage; diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c index 60e9595b77a..b7f9af09348 100644 --- a/source/blender/editors/space_logic/logic_ops.c +++ b/source/blender/editors/space_logic/logic_ops.c @@ -43,6 +43,7 @@ #include "BKE_context.h" #include "BKE_main.h" #include "BKE_sca.h" +#include "BKE_material.h" //for texface convert #include "ED_logic.h" #include "ED_object.h" @@ -57,6 +58,11 @@ #include "logic_intern.h" +// temporary new includes for texface functions +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" + /* ************* Generic Operator Helpers ************* */ static int edit_sensor_poll(bContext *C) { @@ -687,6 +693,36 @@ static void LOGIC_OT_actuator_move(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", logicbricks_move_direction, 1, "Direction", "Move Up or Down"); } +/* ************* TexFace Converter Operator ************* */ +static int texface_convert_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain= CTX_data_main(C); + do_version_tface(bmain, 0); + + return OPERATOR_FINISHED; +} + +static int texface_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return texface_convert_exec(C, op); +} + + static void LOGIC_OT_texface_convert(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "TexFace to Material Converter"; + ot->description = "Convert old texface settings into material. It may create new materials if needed"; + ot->idname= "LOGIC_OT_texface_convert"; + + /* api callbacks */ + ot->invoke= texface_convert_invoke; + ot->exec= texface_convert_exec; +// ot->poll= texface_convert_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + void ED_operatortypes_logic(void) { @@ -699,4 +735,5 @@ void ED_operatortypes_logic(void) WM_operatortype_append(LOGIC_OT_actuator_remove); WM_operatortype_append(LOGIC_OT_actuator_add); WM_operatortype_append(LOGIC_OT_actuator_move); + WM_operatortype_append(LOGIC_OT_texface_convert); } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index b8d33de2e37..42ee6c0f00a 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -64,6 +64,7 @@ #include "GPU_buffers.h" #include "GPU_extensions.h" #include "GPU_draw.h" +#include "GPU_material.h" #include "ED_mesh.h" @@ -207,44 +208,71 @@ static Material *give_current_material_or_def(Object *ob, int matnr) return ma?ma:&defmaterial; } -static int set_draw_settings_cached(int clearcache, int textured, MTFace *texface, int lit, Object *litob, int litmatnr, int doublesided) +/* Icky globals, fix with userdata parameter */ + +static struct TextureDrawState { + Object *ob; + int islit, istex; + int color_profile; + unsigned char obcol[4]; +} Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}}; + +static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw) { + static Material *c_ma; static int c_textured; - static int c_lit; - static int c_doublesided; static MTFace *c_texface; - static Object *c_litob; - static int c_litmatnr; + static int c_backculled; static int c_badtex; + static int c_lit; + Object *litob = NULL; //to get mode to turn off mipmap in painting mode + int backculled = 0; + int alphablend = 0; + int textured = 0; + int lit = 0; + if (clearcache) { - c_textured= c_lit= c_doublesided= -1; + c_textured= c_lit= c_backculled= -1; c_texface= (MTFace*) -1; - c_litob= (Object*) -1; - c_litmatnr= -1; c_badtex= 0; + } else { + textured = gtexdraw.istex; + litob = gtexdraw.ob; + } + + /* convert number of lights into boolean */ + if (gtexdraw.islit) lit = 1; + + if (ma) { + alphablend = ma->game.alpha_blend; + if (ma->mode & MA_SHLESS) lit = 0; + backculled = ma->game.flag & GEMAT_BACKCULL; } if (texface) { - lit = lit && (lit==-1 || texface->mode&TF_LIGHT); - textured = textured && (texface->mode&TF_TEX); - doublesided = texface->mode&TF_TWOSIDE; - } else { - textured = 0; + textured = textured && (texface->tpage); + + /* no material, render alpha if texture has depth=32 */ + if (!ma && BKE_image_has_alpha(texface->tpage)) + alphablend = GPU_BLEND_ALPHA; } - if (doublesided!=c_doublesided) { - if (doublesided) glDisable(GL_CULL_FACE); - else glEnable(GL_CULL_FACE); + else + textured = 0; + + if (backculled!=c_backculled) { + if (backculled) glEnable(GL_CULL_FACE); + else glDisable(GL_CULL_FACE); - c_doublesided= doublesided; + c_backculled= backculled; } if (textured!=c_textured || texface!=c_texface) { if (textured ) { - c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT)); + c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend); } else { - GPU_set_tpage(NULL, 0); + GPU_set_tpage(NULL, 0, 0); c_badtex= 0; } c_textured= textured; @@ -252,10 +280,10 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac } if (c_badtex) lit= 0; - if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) { + if (lit!=c_lit || ma!=c_ma) { if (lit) { - Material *ma= give_current_material_or_def(litob, litmatnr+1); float spec[4]; + if (!ma)ma= give_current_material_or_def(NULL, 0); //default material spec[0]= ma->spec*ma->specr; spec[1]= ma->spec*ma->specg; @@ -273,22 +301,11 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac glDisable(GL_COLOR_MATERIAL); } c_lit= lit; - c_litob= litob; - c_litmatnr= litmatnr; } return c_badtex; } -/* Icky globals, fix with userdata parameter */ - -static struct TextureDrawState { - Object *ob; - int islit, istex; - int color_profile; - unsigned char obcol[4]; -} Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}}; - static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { unsigned char obcol[4]; @@ -318,14 +335,14 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.istex = istex; Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); - set_draw_settings_cached(1, 0, NULL, Gtexdraw.islit, NULL, 0, 0); + set_draw_settings_cached(1, NULL, NULL, Gtexdraw); glShadeModel(GL_SMOOTH); } static void draw_textured_end(void) { /* switch off textures */ - GPU_set_tpage(NULL, 0); + GPU_set_tpage(NULL, 0, 0); glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE); @@ -347,18 +364,22 @@ static void draw_textured_end(void) static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr) { - if (tface && (tface->mode&TF_INVISIBLE)) return 0; + Material *ma= give_current_material(Gtexdraw.ob, matnr+1); + int validtexture=0; + + if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0; - if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) { + validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw); + + if (tface && validtexture) { glColor3ub(0xFF, 0x00, 0xFF); return 2; /* Don't set color */ - } else if (tface && tface->mode&TF_OBCOL) { + } else if (ma && ma->shade_flag&MA_OBCOLOR) { glColor3ubv(Gtexdraw.obcol); return 2; /* Don't set color */ } else if (!mcol) { if (tface) glColor3f(1.0, 1.0, 1.0); else { - Material *ma= give_current_material(Gtexdraw.ob, matnr+1); if(ma) { float col[3]; if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); @@ -375,9 +396,11 @@ static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr) } static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr) { - if (tface && (tface->mode&TF_INVISIBLE)) return 0; + Material *ma= give_current_material(Gtexdraw.ob, matnr+1); - if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) { + if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0; + + if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) { return 2; /* Don't set color */ } else if (tface && tface->mode&TF_OBCOL) { return 2; /* Don't set color */ @@ -399,7 +422,9 @@ static void add_tface_color_layer(DerivedMesh *dm) finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer"); for(i=0;i<dm->getNumFaces(dm);i++) { - if (tface && (tface->mode&TF_INVISIBLE)) { + Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1); + + if (ma && (ma->game.flag&GEMAT_INVISIBLE)) { if( mcol ) memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4); else @@ -409,7 +434,7 @@ static void add_tface_color_layer(DerivedMesh *dm) finalCol[i*4+j].r = 255; } } - else if (tface && mface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, mface[i].mat_nr, TF_TWOSIDE)) { + else if (tface && mface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) { for(j=0;j<4;j++) { finalCol[i*4+j].b = 255; finalCol[i*4+j].g = 0; @@ -493,10 +518,14 @@ static int draw_em_tf_mapped__set_draw(void *userData, int index) static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r) { Mesh *me = (Mesh*)userData; + Material *ma; + + if (me->mface) { + int matnr = me->mface[index].mat_nr; + ma = me->mat[matnr]; + } - if ( (me->mface && me->mface[index].flag & ME_HIDE) || - (me->mtface && (me->mtface[index].mode & TF_INVISIBLE)) - ) { + if ( ma && (ma->game.flag & GEMAT_INVISIBLE)) { return 0; } @@ -529,11 +558,12 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); for(a=0, mf=mface; a<totface; a++, tface++, mf++) { - int mode= tface->mode; int matnr= mf->mat_nr; int mf_smooth= mf->flag & ME_SMOOTH; + Material *mat = me->mat[matnr]; + int mode= mat->game.flag; - if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) { + if (!(mode&GEMAT_INVISIBLE) && (mode&GEMAT_TEXT)) { float v1[3], v2[3], v3[3], v4[3]; char string[MAX_PROPSTRING]; int characters, i, glattrib= -1, badtex= 0; @@ -549,7 +579,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) } } else { - badtex = set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE); + badtex = set_draw_settings_cached(0, tface, mat, Gtexdraw); if (badtex) { if (mcol) mcol+=4; continue; @@ -578,7 +608,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) glNormal3fv(nor); } - GPU_render_text(tface, tface->mode, string, characters, + GPU_render_text(tface, mode, string, characters, (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib); } if (mcol) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index ecdac083aed..e738d5abe69 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -220,16 +220,13 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt) return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID); } -static int check_material_alpha(Base *base, Mesh *me, int glsl) +static int check_material_alpha(Base *base, int glsl) { if(base->flag & OB_FROMDUPLI) return 0; if(G.f & G_PICKSEL) return 0; - - if(me->edit_mesh) - return 0; return (glsl || (base->object->dtx & OB_DRAWTRANSP)); } @@ -2998,12 +2995,16 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D scene->customdata_mask); if(dt>OB_WIRE) { - // no transp in editmode, the fancy draw over goes bad then glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + check_alpha = check_material_alpha(base, glsl); + + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, + (check_alpha)? &do_alpha_pass: NULL); } - draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt); + // transp in editmode makes the fancy draw over go bad + if (!do_alpha_pass) + draw_em_fancy(scene, v3d, rv3d, ob, em, cageDM, finalDM, dt); GPU_end_object_materials(); @@ -3014,7 +3015,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) { glsl = draw_glsl_material(scene, ob, v3d, dt); - check_alpha = check_material_alpha(base, me, glsl); + check_alpha = check_material_alpha(base, glsl); if(dt==OB_SOLID || glsl) { GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 45d832d4739..8227ba87021 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1667,7 +1667,7 @@ static void RestoreState(bContext *C, wmWindow *win) win->queue= queue_back; GPU_state_init(); - GPU_set_tpage(NULL, 0); + GPU_set_tpage(NULL, 0, 0); glPopAttrib(); } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 9a21305457c..cd1c5594822 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -125,14 +125,12 @@ void ED_uvedit_assign_image(Scene *scene, Object *obedit, Image *ima, Image *pre if(uvedit_face_visible(scene, previma, efa, tf)) { if(ima) { tf->tpage= ima; - tf->mode |= TF_TEX; if(ima->id.us==0) id_us_plus(&ima->id); else id_lib_extern(&ima->id); } else { tf->tpage= NULL; - tf->mode &= ~TF_TEX; } update = 1; diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index d75b8db2c4e..55c4ff85a57 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -80,15 +80,15 @@ void GPU_end_object_materials(void); int GPU_enable_material(int nr, void *attribs); void GPU_disable_material(void); -void GPU_set_material_blend_mode(int blendmode); -int GPU_get_material_blend_mode(void); +void GPU_set_material_alpha_blend(int alphablend); +int GPU_get_material_alpha_blend(void); /* TexFace drawing * - this is mutually exclusive with material drawing, a mesh should * be drawn using one or the other * - passing NULL clears the state again */ -int GPU_set_tpage(struct MTFace *tface, int mipmap); +int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp); /* Lights * - returns how many lights were enabled diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 95a08e6d5b3..29ad9c91374 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -94,7 +94,8 @@ typedef enum GPUBlendMode { GPU_BLEND_SOLID = 0, GPU_BLEND_ADD = 1, GPU_BLEND_ALPHA = 2, - GPU_BLEND_CLIP = 4 + GPU_BLEND_CLIP = 4, + GPU_BLEND_ALPHA_SORT = 8 } GPUBlendMode; typedef struct GPUNodeStack { @@ -121,7 +122,7 @@ int GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNode void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); void GPU_material_enable_alpha(GPUMaterial *material); -GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]); +GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7af5ef6ea14..4f79d577ae5 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -95,7 +95,7 @@ void GPU_render_text(MTFace *tface, int mode, const char *textstr, int textlen, unsigned int *col, float *v1, float *v2, float *v3, float *v4, int glattrib) { - if ((mode & TF_BMFONT) && (textlen>0) && tface->tpage) { + if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) { Image* ima = (Image*)tface->tpage; int index, character; float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; @@ -245,7 +245,7 @@ static struct GPUTextureState { int domipmap, linearmipmap; - int alphamode; + int alphablend; float anisotropic; MTFace *lasttface; } GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, 1.f, NULL}; @@ -352,7 +352,7 @@ static void gpu_clear_tpage(void) GTS.curtilemode= 0; GTS.curtileXRep=0; GTS.curtileYRep=0; - GTS.alphamode= -1; + GTS.alphablend= -1; glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); @@ -361,19 +361,19 @@ static void gpu_clear_tpage(void) glDisable(GL_ALPHA_TEST); } -static void gpu_set_blend_mode(GPUBlendMode blendmode) +static void gpu_set_alpha_blend(GPUBlendMode alphablend) { - if(blendmode == GPU_BLEND_SOLID) { + if(alphablend == GPU_BLEND_SOLID) { glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if(blendmode==GPU_BLEND_ADD) { + else if(alphablend==GPU_BLEND_ADD) { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_ALPHA_TEST); } - else if(blendmode==GPU_BLEND_ALPHA) { + else if(ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -389,21 +389,21 @@ static void gpu_set_blend_mode(GPUBlendMode blendmode) glAlphaFunc(GL_GREATER, U.glalphaclip); } } - else if(blendmode==GPU_BLEND_CLIP) { + else if(alphablend==GPU_BLEND_CLIP) { glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); } } -static void gpu_verify_alpha_mode(MTFace *tface) +static void gpu_verify_alpha_blend(int alphablend) { /* verify alpha blending modes */ - if(GTS.alphamode == tface->transp) + if(GTS.alphablend == alphablend) return; - gpu_set_blend_mode(tface->transp); - GTS.alphamode= tface->transp; + gpu_set_alpha_blend(alphablend); + GTS.alphablend= alphablend; } static void gpu_verify_reflection(Image *ima) @@ -608,7 +608,7 @@ static void gpu_verify_repeat(Image *ima) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } -int GPU_set_tpage(MTFace *tface, int mipmap) +int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) { Image *ima; @@ -621,7 +621,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap) ima= tface->tpage; GTS.lasttface= tface; - gpu_verify_alpha_mode(tface); + gpu_verify_alpha_blend(alphablend); gpu_verify_reflection(ima); if(GPU_verify_image(ima, NULL, tface->tile, 1, mipmap)) { @@ -945,12 +945,12 @@ static struct GPUMaterialState { float (*gviewmat)[4]; float (*gviewinv)[4]; - GPUBlendMode *blendmode; - GPUBlendMode blendmode_fixed[FIXEDMAT]; + GPUBlendMode *alphablend; + GPUBlendMode alphablend_fixed[FIXEDMAT]; int alphapass; int lastmatnr, lastretval; - GPUBlendMode lastblendmode; + GPUBlendMode lastalphablend; } GMS = {NULL}; /* fixed function material, alpha handed by caller */ @@ -1000,7 +1000,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O { Material *ma; GPUMaterial *gpumat; - GPUBlendMode blendmode; + GPUBlendMode alphablend; int a; int gamma = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; @@ -1008,7 +1008,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O memset(&GMS, 0, sizeof(GMS)); GMS.lastmatnr = -1; GMS.lastretval = -1; - GMS.lastblendmode = GPU_BLEND_SOLID; + GMS.lastalphablend = GPU_BLEND_SOLID; GMS.gob = ob; GMS.gscene = scene; @@ -1024,12 +1024,12 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O if(GMS.totmat > FIXEDMAT) { GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf"); GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf"); - GMS.blendmode= MEM_callocN(sizeof(*GMS.blendmode)*GMS.totmat, "GMS.matbuf"); + GMS.alphablend= MEM_callocN(sizeof(*GMS.alphablend)*GMS.totmat, "GMS.matbuf"); } else { GMS.matbuf= GMS.matbuf_fixed; GMS.gmatbuf= GMS.gmatbuf_fixed; - GMS.blendmode= GMS.blendmode_fixed; + GMS.alphablend= GMS.alphablend_fixed; } /* no materials assigned? */ @@ -1044,7 +1044,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPU_material_from_blender(GMS.gscene, &defmaterial); } - GMS.blendmode[0]= GPU_BLEND_SOLID; + GMS.alphablend[0]= GPU_BLEND_SOLID; } /* setup materials */ @@ -1060,13 +1060,13 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O if(gpumat) { /* do glsl only if creating it succeed, else fallback */ GMS.gmatbuf[a]= ma; - blendmode = GPU_material_blend_mode(gpumat, ob->col); + alphablend = GPU_material_alpha_blend(gpumat, ob->col); } else { /* fixed function opengl materials */ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob); - blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; if(do_alpha_pass && GMS.alphapass) GMS.matbuf[a].diff[3]= ma->alpha; else @@ -1076,8 +1076,8 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O /* setting do_alpha_pass = 1 indicates this object needs to be * drawn in a second alpha pass for improved blending */ if(do_alpha_pass) { - GMS.blendmode[a]= blendmode; - if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass) + GMS.alphablend[a]= alphablend; + if(ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT) && !GMS.alphapass) *do_alpha_pass= 1; } } @@ -1090,7 +1090,7 @@ int GPU_enable_material(int nr, void *attribs) { GPUVertexAttribs *gattribs = attribs; GPUMaterial *gpumat; - GPUBlendMode blendmode; + GPUBlendMode alphablend; /* no GPU_begin_object_materials, use default material */ if(!GMS.matbuf) { @@ -1131,7 +1131,7 @@ int GPU_enable_material(int nr, void *attribs) /* draw materials with alpha in alpha pass */ GMS.lastmatnr = nr; - GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); + GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); if(GMS.alphapass) GMS.lastretval = !GMS.lastretval; @@ -1145,6 +1145,7 @@ int GPU_enable_material(int nr, void *attribs) GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT)); GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col); GMS.gboundmat= mat; + alphablend= mat->game.alpha_blend; if(GMS.alphapass) glDepthMask(1); } @@ -1153,28 +1154,29 @@ int GPU_enable_material(int nr, void *attribs) glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr].diff); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr].spec); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, GMS.matbuf[nr].hard); + alphablend= GPU_BLEND_SOLID; } /* set (alpha) blending mode */ - blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID; - GPU_set_material_blend_mode(blendmode); + if(!GMS.alphapass) alphablend= GPU_BLEND_SOLID; + GPU_set_material_alpha_blend(alphablend); } return GMS.lastretval; } -void GPU_set_material_blend_mode(int blendmode) +void GPU_set_material_alpha_blend(int alphablend) { - if(GMS.lastblendmode == blendmode) + if(GMS.lastalphablend == alphablend) return; - gpu_set_blend_mode(blendmode); - GMS.lastblendmode = blendmode; + gpu_set_alpha_blend(alphablend); + GMS.lastalphablend = alphablend; } -int GPU_get_material_blend_mode(void) +int GPU_get_material_alpha_blend(void) { - return GMS.lastblendmode; + return GMS.lastalphablend; } void GPU_disable_material(void) @@ -1188,7 +1190,7 @@ void GPU_disable_material(void) GMS.gboundmat= NULL; } - GPU_set_material_blend_mode(GPU_BLEND_SOLID); + GPU_set_material_alpha_blend(GPU_BLEND_SOLID); } void GPU_end_object_materials(void) @@ -1198,12 +1200,12 @@ void GPU_end_object_materials(void) if(GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) { MEM_freeN(GMS.matbuf); MEM_freeN(GMS.gmatbuf); - MEM_freeN(GMS.blendmode); + MEM_freeN(GMS.alphablend); } GMS.matbuf= NULL; GMS.gmatbuf= NULL; - GMS.blendmode= NULL; + GMS.alphablend= NULL; /* resetting the texture matrix after the glScale needed for tiled textures */ if(GTS.tilemode) diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 9aa453af4d6..40186c5a187 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -358,7 +358,7 @@ void GPU_material_enable_alpha(GPUMaterial *material) material->alpha= 1; } -GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]) +GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]) { if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f)) return GPU_BLEND_ALPHA; diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 060b1bf42d1..09255adb829 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -74,6 +74,14 @@ typedef struct VolumeSettings { float ms_spread; } VolumeSettings; +/* Game Engine Options (old Texface mode, transp and flag) */ +typedef struct GameSettings { + int flag; + int alpha_blend; + int face_orientation; + int pad1; +} GameSettings; + typedef struct Material { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ @@ -90,6 +98,7 @@ typedef struct Material { /* end synced with render_types.h */ struct VolumeSettings vol; + struct GameSettings game; float fresnel_mir, fresnel_mir_i; float fresnel_tra, fresnel_tra_i; @@ -166,6 +175,32 @@ typedef struct Material { ListBase gpumaterial; /* runtime */ } Material; + +/* **************** GAME PROPERTIES ********************* */ +// Blend Transparency Options - alpha_blend /* match GPU_material::GPUBlendMode */ +#define GEMAT_SOLID 0 /* GPU_BLEND_SOLID */ +#define GEMAT_ADD 1 /* GPU_BLEND_ADD */ +#define GEMAT_ALPHA 2 /* GPU_BLEND_ALPHA */ +#define GEMAT_CLIP 4 /* GPU_BLEND_CLIP */ +#define GEMAT_ALPHA_SORT 8 /* GPU_BLEND_ALPHA_SORT */ + +// Game Options - flag +#define GEMAT_BACKCULL 16 /* KX_BACKCULL */ +#define GEMAT_SHADED 32 /* KX_LIGHT */ +#define GEMAT_TEXT 64 /* RAS_RENDER_3DPOLYGON_TEXT */ +#define GEMAT_NOPHYSICS 128 +#define GEMAT_INVISIBLE 256 + +// Face Orientation Options - face_orientation +#define GEMAT_NORMAL 0 +#define GEMAT_HALO 512 /* BILLBOARD_SCREENALIGNED */ +#define GEMAT_BILLBOARD 1024 /* BILLBOARD_AXISALIGNED */ +#define GEMAT_SHADOW 2048 /* SHADOW */ + +// Use Textures - not defined directly in the UI +#define GEMAT_TEX 4096 /* KX_TEX */ + + /* **************** MATERIAL ********************* */ /* maximum number of materials per material array. diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 61c4a660992..9d7375b6755 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -247,6 +247,8 @@ typedef struct MRecast{ #define TF_SHAREDVERT 8 #define TF_LIGHT 16 +#define TF_CONVERTED 32 /* tface converted to material */ + #define TF_SHAREDCOL 64 #define TF_TILES 128 /* deprecated */ #define TF_BILLBOARD 256 diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index dcaeb523df5..673e768e71e 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -742,6 +742,61 @@ static void rna_def_material_mtex(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Material_update"); } +static void rna_def_material_gamesettings(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static EnumPropertyItem prop_alpha_blend_items[] = { + {GEMAT_SOLID, "OPAQUE", 0, "Opaque", "Render color of textured face as color"}, + {GEMAT_ADD, "ADD", 0, "Add", "Render face transparent and add color of face"}, + {GEMAT_CLIP, "CLIP", 0, "Alpha Clip", "Use the image alpha values clipped with no blending (binary alpha)"}, + {GEMAT_ALPHA, "ALPHA", 0, "Alpha Blend", "Render polygon transparent, depending on alpha channel of the texture"}, + {GEMAT_ALPHA_SORT, "ALPHA_SORT", 0, "Alpha Sort", "Sort faces for correct alpha drawing (slow, use Alpha Clip instead when possible)"}, + {0, NULL, 0, NULL, NULL}}; + + static EnumPropertyItem prop_face_orientation_items[] = { + {GEMAT_NORMAL,"NORMAL",0,"Normal","No tranformation"}, + {GEMAT_HALO, "HALO", 0, "Halo", "Screen aligned billboard"}, + {GEMAT_BILLBOARD, "BILLBOARD", 0, "Billboard", "Billboard with Z-axis constraint"}, + {GEMAT_SHADOW, "SHADOW", 0, "Shadow", "Faces are used for shadow"}, + {0, NULL, 0, NULL, NULL}}; + + srna= RNA_def_struct(brna, "MaterialGameSettings", NULL); + RNA_def_struct_sdna(srna, "GameSettings"); + RNA_def_struct_nested(brna, srna, "Material"); + RNA_def_struct_ui_text(srna, "Material Game Settings", "Game Engine settings for a Material datablock"); + + prop= RNA_def_property(srna, "back_culling", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GEMAT_BACKCULL); /* use bitflags */ + RNA_def_property_ui_text(prop, "Back Culling", "Hide Back of the face in Game Engine "); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + + prop= RNA_def_property(srna, "text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GEMAT_TEXT); /* use bitflags */ + RNA_def_property_ui_text(prop, "Text", "Use material as text in Game Engine "); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + + prop= RNA_def_property(srna, "invisible", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GEMAT_INVISIBLE); /* use bitflags */ + RNA_def_property_ui_text(prop, "Invisible", "Make face invisible"); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + + prop= RNA_def_property(srna, "alpha_blend", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "alpha_blend"); + RNA_def_property_enum_items(prop, prop_alpha_blend_items); + RNA_def_property_ui_text(prop, "Blend Mode", "Blend Mode for Transparent Faces"); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + + prop= RNA_def_property(srna, "face_orientation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_face_orientation_items); + RNA_def_property_ui_text(prop, "Face Orientations", "Especial face orientation options"); + + prop= RNA_def_property(srna, "physics", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GEMAT_NOPHYSICS); /* use bitflags */ + RNA_def_property_ui_text(prop, "Physics", "Use physics properties of materials "); +} + static void rna_def_material_colors(StructRNA *srna) { PropertyRNA *prop; @@ -1887,6 +1942,13 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Material_physics_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Physics", "Game physics settings"); + /* game settings */ + prop= RNA_def_property(srna, "game_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "game"); + RNA_def_property_struct_type(prop, "MaterialGameSettings"); + RNA_def_property_ui_text(prop, "Game Settings", "Game material settings"); + /* nodetree */ prop= RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); @@ -1932,6 +1994,7 @@ void RNA_def_material(BlenderRNA *brna) rna_def_material_mtex(brna); rna_def_material_strand(brna); rna_def_material_physics(brna); + rna_def_material_gamesettings(brna); RNA_api_material(srna); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 5466e758023..1bbdc7cc853 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1420,6 +1420,9 @@ static void rna_def_mtface(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Image", ""); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + //XXX to be deleted soon -- left for now in case we need it for debug + //XXX it should be out before Blender 2.6 (after texface to material patch) + prop= RNA_def_property(srna, "use_image", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", TF_TEX); RNA_def_property_ui_text(prop, "Tex", "Render face with texture"); @@ -1486,6 +1489,9 @@ static void rna_def_mtface(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Transparency", "Transparency blending mode"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); + //XXX to be deleted soon -- left for now in case we need it for debug + //XXX it should be out before Blender 2.6 (after texface to material patch) + prop= RNA_def_property(srna, "select_uv", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TF_SEL1); RNA_def_property_array(prop, 4); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 873d61eba06..774e21297da 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1828,7 +1828,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem material_items[] ={ - {GAME_MAT_TEXFACE, "TEXTURE_FACE", 0, "Texture Face", "Single texture face materials"}, + {GAME_MAT_TEXFACE, "SINGLETEXTURE", 0, "Singletexture", "Singletexture face materials"}, {GAME_MAT_MULTITEX, "MULTITEXTURE", 0, "Multitexture", "Multitexture materials"}, {GAME_MAT_GLSL, "GLSL", 0, "GLSL", "OpenGL shading language shaders"}, {0, NULL, 0, NULL, NULL}}; diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 912c14adfdd..0c343332736 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -369,7 +369,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } if(override_image) { - tface->mode = TF_TEX; tface->tpage = image; } } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d4b43cd7ac1..2c2fd052b5d 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -144,6 +144,8 @@ extern "C" { #include "BKE_cdderivedmesh.h" #include "BKE_DerivedMesh.h" #include "BKE_material.h" /* give_current_material */ +#include "BKE_image.h" +#include "IMB_imbuf_types.h" extern Material defmaterial; /* material.c */ } @@ -195,7 +197,7 @@ extern "C" { } #endif -static int default_face_mode = TF_DYNAMIC; +static bool default_light_mode = 0; static unsigned int KX_rgbaint2uint_new(unsigned int icol) { @@ -234,9 +236,9 @@ static unsigned int KX_Mcol2uint_new(MCol col) return out_color.integer; } -static void SetDefaultFaceType(Scene* scene) +static void SetDefaultLightMode(Scene* scene) { - default_face_mode = TF_DYNAMIC; + default_light_mode = false; Scene *sce_iter; Base *base; @@ -244,7 +246,7 @@ static void SetDefaultFaceType(Scene* scene) { if (base->object->type == OB_LAMP) { - default_face_mode = TF_DYNAMIC|TF_LIGHT; + default_light_mode = true; return; } } @@ -353,41 +355,41 @@ bool ConvertMaterial( // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; + material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; + // cast shadows? material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0; MTex *mttmp = 0; numchan = getNumTexChannels(mat); int valid_index = 0; - // use the face texture if - // 1) it is set in the buttons - // 2) we have a face texture and a material but no valid texture in slot 1 + /* In Multitexture use the face texture if and only if + * it is set in the buttons + * In GLSL is not working yet :/ 3.2011 */ bool facetex = false; if(validface && mat->mode &MA_FACETEXTURE) facetex = true; - if(validface && !mat->mtex[0]) - facetex = true; - if(validface && mat->mtex[0]) { - MTex *tmp = mat->mtex[0]; - if(!tmp->tex || (tmp->tex && !tmp->tex->ima)) - facetex = true; - } + numchan = numchan>MAXTEX?MAXTEX:numchan; + if (facetex && numchan == 0) numchan = 1; // foreach MTex for(int i=0; i<numchan; i++) { // use face tex if(i==0 && facetex ) { + facetex = false; 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->flag[i] |= MIPMAP; + material->flag[i] |= ( mat->game.alpha_blend & GEMAT_ALPHA_SORT )?USEALPHA:0; + material->flag[i] |= ( mat->game.alpha_blend & GEMAT_ALPHA )?USEALPHA:0; + material->flag[i] |= ( mat->game.alpha_blend & GEMAT_ADD )?CALCALPHA:0; + if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; else @@ -405,11 +407,6 @@ bool ConvertMaterial( material->mapping[i].mapping |= USEUV; } - if(material->ras_mode & USE_LIGHT) - material->ras_mode &= ~USE_LIGHT; - if(tface->mode & TF_LIGHT) - material->ras_mode |= USE_LIGHT; - valid_index++; } else { @@ -567,25 +564,31 @@ bool ConvertMaterial( material->ras_mode |= (mat->material_type == MA_TYPE_WIRE)? WIRE: 0; } - else { + else { // No Material int valid = 0; // check for tface tex to fallback on if( validface ){ - - // no light bugfix - if(tface->mode) material->ras_mode |= USE_LIGHT; - material->img[0] = (Image*)(tface->tpage); // ------------------------ if(material->img[0]) { material->texname[0] = material->img[0]->id.name; 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; + + /* see if depth of the image is 32bits */ + if(BKE_image_has_alpha(material->img[0])) { + material->flag[0] |= USEALPHA; + material->alphablend = GEMAT_ALPHA; + } + else + material->alphablend = GEMAT_SOLID; + valid++; } } + else + material->alphablend = GEMAT_SOLID; + material->SetUsers(-1); material->num_enabled = valid; material->IdMode = TEXFACE; @@ -598,6 +601,9 @@ bool ConvertMaterial( material->matcolor[2] = 0.5f; material->spec_f = 0.5f; material->ref = 0.8f; + + // No material - old default TexFace properties + material->ras_mode |= USE_LIGHT; } MT_Point2 uv[4]; MT_Point2 uv2[4]; @@ -606,13 +612,10 @@ bool ConvertMaterial( uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f); + /* No material, what to do? let's see what is in the UV and set the material accordingly + light and visible is always on */ if( validface ) { - - material->ras_mode |= (tface->mode & TF_INVISIBLE)?0:POLY_VIS; - - material->transp = tface->transp; material->tile = tface->tile; - material->mode = tface->mode; uv[0].setValue(tface->uv[0]); uv[1].setValue(tface->uv[1]); @@ -625,31 +628,26 @@ bool ConvertMaterial( } else { // nothing at all - material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT)); - material->mode = default_face_mode; - material->transp = TF_SOLID; + material->alphablend = GEMAT_SOLID; material->tile = 0; uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); } + if (validmat && validface) { + material->alphablend = mat->game.alpha_blend; + } + // with ztransp enabled, enforce alpha blending mode - if(validmat && (mat->mode & MA_TRANSP) && (mat->mode & MA_ZTRANSP) && (material->transp == TF_SOLID)) - material->transp = TF_ALPHA; + if(validmat && (mat->mode & MA_TRANSP) && (mat->mode & MA_ZTRANSP) && (material->alphablend == GEMAT_SOLID)) + material->alphablend = GEMAT_ALPHA; // always zsort alpha + add - if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) { + if((ELEM3(material->alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) || texalpha) && (material->alphablend != GEMAT_CLIP )) { material->ras_mode |= ALPHA; - material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; + material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0; } - // collider or not? - material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0; - - // these flags are irrelevant at this point, remove so they - // don't hurt material bucketing - material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX); - // get uv sets if(validmat) { @@ -706,8 +704,8 @@ bool ConvertMaterial( unsigned int rgb[4]; GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]); - // swap the material color, so MCol on TF_BMFONT works - if (validmat && type==1 && (tface && tface->mode & TF_BMFONT)) + // swap the material color, so MCol on bitmap font works + if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT)) { rgb[0] = KX_rgbaint2uint_new(rgb[0]); rgb[1] = KX_rgbaint2uint_new(rgb[1]); @@ -864,10 +862,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, layers, converter->GetGLSLMaterials()); - visible = ((bl_mat->ras_mode & POLY_VIS)!=0); - collider = ((bl_mat->ras_mode & COLLIDER)!=0); - twoside = ((bl_mat->mode & TF_TWOSIDE)!=0); - /* vertex colors and uv's were stored in bl_mat temporarily */ bl_mat->GetConversionRGB(rgb); rgb0 = rgb[0]; rgb1 = rgb[1]; @@ -885,7 +879,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, if (kx_blmat == NULL) kx_blmat = new KX_BlenderMaterial(); - kx_blmat->Initialize(scene, bl_mat); + kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL)); polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat); } else { @@ -893,37 +887,59 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, Image* bima = (tface)? (Image*)tface->tpage: NULL; imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - char transp=0; - short mode=0, tile=0; + char alpha_blend=0; + short tile=0; int tilexrep=4,tileyrep = 4; - + + /* set material properties - old TexFace */ + if (ma) { + alpha_blend = ma->game.alpha_blend; + /* Commented out for now. If we ever get rid of + * "Texture Face/Singletexture" we can then think about it */ + + /* Texture Face mode ignores texture but requires "Face Textures to be True "*/ + /** + if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) { + bima = NULL; + imastr = ""; + alpha_blend = GEMAT_SOLID; + } + else + alpha_blend = ma->game.alpha_blend; + */ + } + /* check for tface tex to fallback on */ + else { + if (bima) { + /* see if depth of the image is 32 */ + if (BKE_image_has_alpha(bima)) + alpha_blend = GEMAT_ALPHA; + else + alpha_blend = GEMAT_SOLID; + } + else { + alpha_blend = GEMAT_SOLID; + } + } + if (bima) { tilexrep = bima->xrep; tileyrep = bima->yrep; } - /* get tface properties if available */ + /* set UV properties */ 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; - - visible = !(tface->mode & TF_INVISIBLE); - twoside = ((tface->mode & TF_TWOSIDE)!=0); - uv0.setValue(tface->uv[0]); uv1.setValue(tface->uv[1]); uv2.setValue(tface->uv[2]); if (mface->v4) uv3.setValue(tface->uv[3]); + + tile = tface->tile; } else { - /* no texfaces, set COLLSION true and everything else FALSE */ - mode = default_face_mode; - transp = TF_SOLID; + /* no texfaces */ tile = 0; } @@ -964,16 +980,20 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, if (mface->v4) rgb3 = KX_rgbaint2uint_new(color); } - + // only zsort alpha + add - bool alpha = (transp == TF_ALPHA || transp == TF_ADD); - bool zsort = (mode & TF_ALPHASORT)? alpha: 0; + bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT); + bool zsort = (alpha_blend == GEMAT_ALPHA_SORT); + bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode; + + // don't need zort anymore, deal as if it it's alpha blend + if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA; if (kx_polymat == NULL) kx_polymat = new KX_PolygonMaterial(); kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr, tile, tilexrep, tileyrep, - mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol); + alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol); polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat); if (ma) { @@ -987,6 +1007,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, } } + // set render flags + if (ma) + { + visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); + twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); + collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); + } + else{ + visible = true; + twoside = false; + collider = true; + } + /* mark face as flat, so vertices are split */ bool flat = (mface->flag & ME_SMOOTH) == 0; @@ -2035,7 +2068,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, logicmgr->RegisterActionName(curAct->id.name + 2, curAct); } - SetDefaultFaceType(blenderscene); + SetDefaultLightMode(blenderscene); // Let's support scene set. // Beware of name conflict in linked data, it will not crash but will create confusion // in Python scripting and in certain actuators (replace mesh). Linked scene *should* have diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 4ae937cdcd6..6680e9556b9 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -27,7 +27,7 @@ BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lig mGPUMat(NULL) { mBlenderScene = scene->GetBlenderScene(); - mBlendMode = GPU_BLEND_SOLID; + mAlphaBlend = GPU_BLEND_SOLID; ReloadMaterial(); } @@ -148,12 +148,12 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol); - mBlendMode = GPU_material_blend_mode(gpumat, obcol); + mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } -int BL_BlenderShader::GetBlendMode() +int BL_BlenderShader::GetAlphaBlend() { - return mBlendMode; + return mAlphaBlend; } bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 2f22e121b8c..f187d93d648 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -63,7 +63,7 @@ private: struct Scene *mBlenderScene; struct Material *mMat; int mLightLayer; - int mBlendMode; + int mAlphaBlend; GPUMaterial *mGPUMat; bool VerifyShader() @@ -86,7 +86,7 @@ public: void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); void ReloadMaterial(); - int GetBlendMode(); + int GetAlphaBlend(); void SetScene(KX_Scene *scene) { diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 25fd5467e93..fd0756d067d 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -52,12 +52,11 @@ void BL_Material::Initialize() speccolor[0] = 1.f; speccolor[1] = 1.f; speccolor[2] = 1.f; - transp = 0; + alphablend = 0; hard = 50.f; spec_f = 0.5f; alpha = 1.f; emit = 0.f; - mode = 0; material = 0; tface = 0; materialindex = 0; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index c0440e66501..2c6316ea32b 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -68,7 +68,7 @@ public: float matcolor[4]; float speccolor[3]; - short transp, pad; + short alphablend, pad; float hard, spec_f; float alpha, emit, color_blend[MAXTEX], ref; @@ -76,7 +76,6 @@ public: int blend_mode[MAXTEX]; - int mode; int num_enabled; BL_Mapping mapping[MAXTEX]; @@ -151,14 +150,16 @@ enum BL_flag // BL_Material::ras_mode enum BL_ras_mode { - POLY_VIS=1, + // POLY_VIS=1, COLLIDER=2, ZSORT=4, ALPHA=8, // TRIANGLE=16, USE_LIGHT=32, WIRE=64, - CAST_SHADOW=128 + CAST_SHADOW=128, + TEX=256, + TWOSIDED=512 }; // ------------------------------------- diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 33da17cc505..1a1e046f54c 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -34,6 +34,8 @@ #include "DNA_meshdata_types.h" #include "BKE_mesh.h" // ------------------------------------ +#include "BLI_utildefines.h" + #define spit(x) std::cout << x << std::endl; BL_Shader *KX_BlenderMaterial::mLastShader = NULL; @@ -56,21 +58,24 @@ KX_BlenderMaterial::KX_BlenderMaterial() } void KX_BlenderMaterial::Initialize( - KX_Scene *scene, - BL_Material *data) + KX_Scene *scene, + BL_Material *data, + GameSettings *game) { RAS_IPolyMaterial::Initialize( - data->texname[0], - data->matname, - data->materialindex, - data->tile, - data->tilexrep[0], - data->tileyrep[0], - data->mode, - data->transp, - ((data->ras_mode &ALPHA)!=0), - ((data->ras_mode &ZSORT)!=0) - ); + data->texname[0], + data->matname, + data->materialindex, + data->tile, + data->tilexrep[0], + data->tileyrep[0], + data->alphablend, + ((data->ras_mode &ALPHA)!=0), + ((data->ras_mode &ZSORT)!=0), + ((data->ras_mode &USE_LIGHT)!=0), + ((data->ras_mode &TEX)), + game + ); mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -99,7 +104,7 @@ void KX_BlenderMaterial::Initialize( for(int i=0; i<mMaterial->num_enabled; i++) { m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]); } - m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); + m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT)); } KX_BlenderMaterial::~KX_BlenderMaterial() @@ -231,7 +236,7 @@ void KX_BlenderMaterial::OnExit() } if( mMaterial->tface ) - GPU_set_tpage(mMaterial->tface, 1); + GPU_set_tpage(mMaterial->tface, 1, mMaterial->alphablend); } @@ -247,7 +252,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) mLastShader = NULL; } - ras->SetBlendingMode(TF_SOLID); + ras->SetAlphaBlend(TF_SOLID); BL_Texture::DisableAllTextures(); return; } @@ -268,11 +273,11 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - ras->SetBlendingMode(mMaterial->transp); + ras->SetAlphaBlend(mMaterial->alphablend); } else { - ras->SetBlendingMode(TF_SOLID); - ras->SetBlendingMode(-1); // indicates custom mode + ras->SetAlphaBlend(TF_SOLID); + ras->SetAlphaBlend(-1); // indicates custom mode // tested to be valid enums glEnable(GL_BLEND); @@ -283,7 +288,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras) { if( !enable || !mBlenderShader->Ok() ) { - ras->SetBlendingMode(TF_SOLID); + ras->SetAlphaBlend(TF_SOLID); // frame cleanup. if(mLastBlenderShader) { @@ -297,7 +302,7 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras } if(!mBlenderShader->Equals(mLastBlenderShader)) { - ras->SetBlendingMode(mMaterial->transp); + ras->SetAlphaBlend(mMaterial->alphablend); if(mLastBlenderShader) mLastBlenderShader->SetProg(false); @@ -314,14 +319,14 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) BL_Texture::DisableAllTextures(); if( !enable ) { - ras->SetBlendingMode(TF_SOLID); + ras->SetAlphaBlend(TF_SOLID); return; } BL_Texture::ActivateFirst(); if( mMaterial->IdMode == DEFAULT_BLENDER ) { - ras->SetBlendingMode(mMaterial->transp); + ras->SetAlphaBlend(mMaterial->alphablend); return; } @@ -331,7 +336,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); - ras->SetBlendingMode(mMaterial->transp); + ras->SetAlphaBlend(mMaterial->alphablend); } return; } @@ -354,11 +359,11 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - ras->SetBlendingMode(mMaterial->transp); + ras->SetAlphaBlend(mMaterial->alphablend); } else { - ras->SetBlendingMode(TF_SOLID); - ras->SetBlendingMode(-1); // indicates custom mode + ras->SetAlphaBlend(TF_SOLID); + ras->SetAlphaBlend(-1); // indicates custom mode glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); @@ -393,15 +398,15 @@ KX_BlenderMaterial::ActivatShaders( else tmp->setShaderData(false, rasty); - if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) + if (mMaterial->ras_mode &TWOSIDED) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { - if((mMaterial->ras_mode &WIRE)!=0) + if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); } @@ -438,15 +443,15 @@ KX_BlenderMaterial::ActivateBlenderShaders( else tmp->setBlenderShaderData(false, rasty); - if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) + if (mMaterial->ras_mode &TWOSIDED) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { - if((mMaterial->ras_mode &WIRE)!=0) + if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); } @@ -487,15 +492,15 @@ KX_BlenderMaterial::ActivateMat( else tmp->setTexData( false,rasty); - if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) + if (mMaterial->ras_mode &TWOSIDED) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { - if((mMaterial->ras_mode &WIRE)!=0) + if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); } @@ -570,17 +575,17 @@ void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasteriz mShader->Update(ms, rasty); } else if(mBlenderShader && GLEW_ARB_shader_objects) { - int blendmode; + int alphablend; mBlenderShader->Update(ms, rasty); /* we do blend modes here, because they can change per object * with the same material due to obcolor/obalpha */ - blendmode = mBlenderShader->GetBlendMode(); - if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) - blendmode = mMaterial->transp; + alphablend = mBlenderShader->GetAlphaBlend(); + if(ELEM3(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID) + alphablend = mMaterial->alphablend; - rasty->SetBlendingMode(blendmode); + rasty->SetAlphaBlend(alphablend); } } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 766e20be825..236bd6afdc8 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -38,7 +38,8 @@ public: KX_BlenderMaterial(); void Initialize( class KX_Scene* scene, - BL_Material* mat + BL_Material* mat, + GameSettings* game ); virtual ~KX_BlenderMaterial(); diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index d32f267f0e0..098c136bfa3 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -78,10 +78,10 @@ void KX_PolygonMaterial::Initialize( int tile, int tilexrep, int tileyrep, - int mode, - int transp, + int alphablend, bool alpha, bool zsort, + bool light, int lightlayer, struct MTFace* tface, unsigned int* mcol) @@ -93,10 +93,12 @@ void KX_PolygonMaterial::Initialize( tile, tilexrep, tileyrep, - mode, - transp, + alphablend, alpha, - zsort); + zsort, + light, + (texname && texname != ""?true:false), /* if we have a texture we have image */ + ma?&ma->game:NULL); m_tface = tface; m_mcol = mcol; m_material = ma; @@ -168,7 +170,7 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - GPU_set_tpage(NULL, 0); + GPU_set_tpage(NULL, 0, 0); cachingInfo = GetCachingInfo(); @@ -176,15 +178,15 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c { Image *ima = (Image*)m_tface->tpage; GPU_update_image_time(ima, rasty->GetTime()); - GPU_set_tpage(m_tface, 1); + GPU_set_tpage(m_tface, 1, m_alphablend); } else - GPU_set_tpage(NULL, 0); + GPU_set_tpage(NULL, 0, 0); - if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - rasty->SetCullFace(false); - else + if(m_drawingmode & RAS_IRasterizer::KX_BACKCULL) rasty->SetCullFace(true); + else + rasty->SetCullFace(false); if ((m_drawingmode & RAS_IRasterizer::KX_LINES) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) @@ -318,7 +320,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") if (PyArg_ParseTuple(args, "O!:setTexture", &PyCapsule_Type, &pytface)) { MTFace *tface = (MTFace*) PyCapsule_GetPointer(pytface, KX_POLYGONMATERIAL_CAPSULE_ID); - GPU_set_tpage(tface, 1); + GPU_set_tpage(tface, 1, m_alphablend); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 3520995def3..b09ddd39141 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -78,10 +78,10 @@ public: int tile, int tilexrep, int tileyrep, - int mode, - int transp, + int alphablend, bool alpha, bool zsort, + bool light, int lightlayer, struct MTFace* tface, unsigned int* mcol); diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 5a1b52489b4..9948f48d7f3 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -36,6 +36,7 @@ #include "DNA_image_types.h" #include "DNA_meshdata_types.h" +#include "DNA_material_types.h" void RAS_IPolyMaterial::Initialize( const STR_String& texname, @@ -44,10 +45,12 @@ void RAS_IPolyMaterial::Initialize( int tile, int tilexrep, int tileyrep, - int mode, - int transp, + int alphablend, bool alpha, - bool zsort) + bool zsort, + bool light, + bool image, + struct GameSettings* game) { m_texturename = texname; m_materialname = matname; @@ -55,10 +58,10 @@ void RAS_IPolyMaterial::Initialize( m_tile = tile; m_tilexrep = tilexrep; m_tileyrep = tileyrep; - m_drawingmode = mode; - m_transp = transp; + m_alphablend = alphablend; m_alpha = alpha; m_zsort = zsort; + m_light = light; m_polymatid = m_newpolymatid++; m_flag = 0; m_multimode = 0; @@ -66,6 +69,7 @@ void RAS_IPolyMaterial::Initialize( m_specular.setValue(0.5,0.5,0.5); m_specularity = 1.0; m_diffuse.setValue(0.5,0.5,0.5); + m_drawingmode = ConvertFaceMode(game, image); } RAS_IPolyMaterial::RAS_IPolyMaterial() @@ -75,9 +79,10 @@ RAS_IPolyMaterial::RAS_IPolyMaterial() m_tilexrep(0), m_tileyrep(0), m_drawingmode (0), - m_transp(0), + m_alphablend(0), m_alpha(false), m_zsort(false), + m_light(false), m_materialindex(0), m_polymatid(0), m_flag(0), @@ -95,8 +100,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int tile, int tilexrep, int tileyrep, - int mode, - int transp, + int alphablend, bool alpha, bool zsort) : m_texturename(texname), @@ -104,8 +108,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_tile(tile), m_tilexrep(tilexrep), m_tileyrep(tileyrep), - m_drawingmode (mode), - m_transp(transp), + m_alphablend(alphablend), m_alpha(alpha), m_zsort(zsort), m_materialindex(materialindex), @@ -128,9 +131,9 @@ 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_texturename.hash() == lhs.m_texturename.hash() && - this->m_materialname.hash() == lhs.m_materialname.hash() + this->m_alphablend == lhs.m_alphablend && + this->m_texturename.hash() == lhs.m_texturename.hash() && + this->m_materialname.hash() == lhs.m_materialname.hash() ); return test; @@ -141,9 +144,10 @@ 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_transp == lhs.m_transp && + this->m_alphablend == lhs.m_alphablend && this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && + this->m_light == lhs.m_light && this->m_drawingmode == lhs.m_drawingmode && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() @@ -151,6 +155,21 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const } } +int RAS_IPolyMaterial::ConvertFaceMode(struct GameSettings *game, bool image) const +{ + if (!game) return (image?GEMAT_TEX:0); + + int modefinal = 0; + + int orimode = game->face_orientation; + int alpha_blend = game->alpha_blend; + int flags = game->flag & (GEMAT_TEXT | GEMAT_BACKCULL); + + modefinal = orimode | alpha_blend | flags; + modefinal |= (image ? GEMAT_TEX : 0); + + return modefinal; +} void RAS_IPolyMaterial::GetMaterialRGBAColor(unsigned char *rgba) const { @@ -241,7 +260,7 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const else if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID); else if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW); else - dolights = (m_drawingmode & RAS_IRasterizer::KX_LIGHT)!=0; + dolights = m_light; return dolights; } diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 2a5c6a179b6..69d07713c49 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -49,6 +49,7 @@ struct Material; struct Image; struct Scene; class SCA_IScene; +struct GameSettings; enum MaterialProps { @@ -78,10 +79,11 @@ protected: STR_HashedString m_materialname; //also needed for touchsensor int m_tile; int m_tilexrep,m_tileyrep; - int m_drawingmode; // tface->mode - int m_transp; + int m_drawingmode; + int m_alphablend; bool m_alpha; bool m_zsort; + bool m_light; int m_materialindex; unsigned int m_polymatid; @@ -102,9 +104,9 @@ public: // care! these are taken from blender polygonflags, see file DNA_mesh_types.h for #define TF_BILLBOARD etc. enum MaterialFlags { - BILLBOARD_SCREENALIGNED = 256, - BILLBOARD_AXISALIGNED = 4096, - SHADOW =8192 + BILLBOARD_SCREENALIGNED = 512, /* GEMAT_HALO */ + BILLBOARD_AXISALIGNED = 1024, /* GEMAT_BILLBOARD */ + SHADOW =2048 /* GEMAT_SHADOW */ }; RAS_IPolyMaterial(); @@ -114,7 +116,6 @@ public: int tile, int tilexrep, int tileyrep, - int mode, int transp, bool alpha, bool zsort); @@ -124,10 +125,13 @@ public: int tile, int tilexrep, int tileyrep, - int mode, int transp, bool alpha, - bool zsort); + bool zsort, + bool light, + bool image, + struct GameSettings* game); + virtual ~RAS_IPolyMaterial() {}; /** @@ -174,6 +178,11 @@ public: virtual void Replace_IScene(SCA_IScene *val) {}; /* overridden by KX_BlenderMaterial */ + /** + * @return the equivalent drawing mode for the material settings (equivalent to old TexFace tface->mode). + */ + int ConvertFaceMode(struct GameSettings *game, bool image) const; + /* * PreCalculate texture gen */ diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 877a7219a1c..2988aa4effb 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -68,11 +68,7 @@ class RAS_IRasterizer public: RAS_IRasterizer(RAS_ICanvas* canv){}; virtual ~RAS_IRasterizer(){}; - /** - */ - enum { - RAS_RENDER_3DPOLYGON_TEXT = 16384 /* TF_BMFONT */ - }; + /** * Drawing types */ @@ -106,9 +102,9 @@ public: /** */ enum { - KX_TEX = 4, /* TF_TEX */ - KX_LIGHT = 16, /* TF_LIGHT */ - KX_TWOSIDE = 512, /* TF_TWOSIDE */ + RAS_RENDER_3DPOLYGON_TEXT = 64, /* GEMAT_TEXT */ + KX_BACKCULL = 16, /* GEMAT_BACKCULL */ + KX_TEX = 4096, /* GEMAT_TEX */ KX_LINES = 32768 }; @@ -417,7 +413,7 @@ public: virtual int GetMotionBlurState()=0; virtual void SetMotionBlurState(int newstate)=0; - virtual void SetBlendingMode(int blendmode)=0; + virtual void SetAlphaBlend(int alphablend)=0; virtual void SetFrontFace(bool ccw)=0; virtual void SetAnisotropicFiltering(short level)=0; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 6ad9e591474..d9039a2a68d 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -89,7 +89,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), - //m_last_blendmode(GPU_BLEND_SOLID), + //m_last_alphablend(GPU_BLEND_SOLID), m_last_frontface(true), m_materialCachingInfo(0) { @@ -126,8 +126,8 @@ bool RAS_OpenGLRasterizer::Init() glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); - //m_last_blendmode = GPU_BLEND_SOLID; - GPU_set_material_blend_mode(GPU_BLEND_SOLID); + //m_last_alphablend = GPU_BLEND_SOLID; + GPU_set_material_alpha_blend(GPU_BLEND_SOLID); glFrontFace(GL_CCW); m_last_frontface = true; @@ -303,8 +303,8 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); - //m_last_blendmode = GPU_BLEND_SOLID; - GPU_set_material_blend_mode(GPU_BLEND_SOLID); + //m_last_alphablend = GPU_BLEND_SOLID; + GPU_set_material_alpha_blend(GPU_BLEND_SOLID); glFrontFace(GL_CCW); m_last_frontface = true; @@ -873,10 +873,10 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ // handle two-side - if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_TWOSIDE) - this->SetCullFace(false); - else + if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL) this->SetCullFace(true); + else + this->SetCullFace(false); if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { // GetMaterialIndex return the original mface material index, @@ -890,9 +890,9 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) else memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); // DM draw can mess up blending mode, restore at the end - int current_blend_mode = GPU_get_material_blend_mode(); + int current_blend_mode = GPU_get_material_alpha_blend(); ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); - GPU_set_material_blend_mode(current_blend_mode); + GPU_set_material_alpha_blend(current_blend_mode); } else { //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); current_blmat_nr = current_polymat->GetMaterialIndex(); @@ -1204,36 +1204,36 @@ void RAS_OpenGLRasterizer::DisableMotionBlur() m_motionblurvalue = -1.0; } -void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) +void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend) { - GPU_set_material_blend_mode(blendmode); + GPU_set_material_alpha_blend(alphablend); /* - if(blendmode == m_last_blendmode) + if(alphablend == m_last_alphablend) return; - if(blendmode == GPU_BLEND_SOLID) { + if(alphablend == GPU_BLEND_SOLID) { glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if(blendmode == GPU_BLEND_ADD) { + else if(alphablend == GPU_BLEND_ADD) { glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); } - else if(blendmode == GPU_BLEND_ALPHA) { + else if(alphablend == GPU_BLEND_ALPHA) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); } - else if(blendmode == GPU_BLEND_CLIP) { + else if(alphablend == GPU_BLEND_CLIP) { glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); } - m_last_blendmode = blendmode; + m_last_alphablend = alphablend; */ } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index c0e02f6df77..cbfa49510a5 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -111,7 +111,7 @@ protected: TexCoGen m_attrib[RAS_MAX_ATTRIB]; int m_texco_num; int m_attrib_num; - //int m_last_blendmode; + //int m_last_alphablend; bool m_last_frontface; /** Stores the caching information for the last material activated. */ @@ -312,7 +312,7 @@ public: m_motionblur = newstate; }; - virtual void SetBlendingMode(int blendmode); + virtual void SetAlphaBlend(int alphablend); virtual void SetFrontFace(bool ccw); virtual void SetAnisotropicFiltering(short level); |