3D View: add Backface Culling option, to hide faces when seen from the back side,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 25 May 2012 09:26:47 +0000 (09:26 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 25 May 2012 09:26:47 +0000 (09:26 +0000)
found in the Display panel.

Patch by Simon Kirk and Irie Shinsuke, refactored to also work for non-mesh objects
and avoid globals.

release/scripts/startup/bl_ui/space_view3d.py
source/blender/editors/space_view3d/drawobject.c
source/blender/gpu/intern/gpu_draw.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index b375150d6627722aad5755d2706a4a08a81503b6..397bdc0d74efd4de0e639b446995b4b14658fb94 100644 (file)
@@ -2391,6 +2391,8 @@ class VIEW3D_PT_view3d_display(Panel):
             col.prop(gs, "material_mode", text="")
             col.prop(view, "show_textured_solid")
 
+        col.prop(view, "show_backface_culling")            
+
         layout.separator()
 
         region = view.region_quadview
index 780f4a2d86a3f02f401b1f8d601b278eac08e20d..a5f3df4257a4624bc703956cd5640464be0aa45a 100644 (file)
@@ -3610,7 +3610,13 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                else if (ob->modifiers.first || obedit->modifiers.first) {}
                else drawlinked = 1;
        }
-       
+
+       /* backface culling */
+       if (v3d->flag2 & V3D_BACKFACE_CULLING) {
+               glEnable(GL_CULL_FACE);
+               glCullFace(GL_BACK);
+       }
+
        if (ob == obedit || drawlinked) {
                DerivedMesh *finalDM, *cageDM;
                
@@ -3669,6 +3675,9 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                        }
                }
        }
+
+       if (v3d->flag2 & V3D_BACKFACE_CULLING)
+               glDisable(GL_CULL_FACE);
        
        return retval;
 }
@@ -3939,7 +3948,17 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
        const short solid = (dt > OB_WIRE);
        int retval = 0;
 
+       /* backface culling */
+       if(v3d->flag2 & V3D_BACKFACE_CULLING) {
+               /* not all displists use same in/out normal direction convention */
+               glEnable(GL_CULL_FACE);
+               glCullFace((ob->type == OB_MBALL) ? GL_BACK : GL_FRONT);
+       }
+
        if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) {
+               if (v3d->flag2 & V3D_BACKFACE_CULLING)
+                       glDisable(GL_CULL_FACE);
+
                return 0;
        }
 
@@ -4045,6 +4064,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
                        break;
        }
        
+       if (v3d->flag2 & V3D_BACKFACE_CULLING)
+               glDisable(GL_CULL_FACE);
+
        return retval;
 }
 
index 604e8f8d50e0025a521bbae62e79376da04b5f76..fb277815878131e38c06fa8b55142fe541f8da79 100644 (file)
@@ -1017,6 +1017,8 @@ static struct GPUMaterialState {
        float (*gviewmat)[4];
        float (*gviewinv)[4];
 
+       int backface_culling;
+
        GPUBlendMode *alphablend;
        GPUBlendMode alphablend_fixed[FIXEDMAT];
        int use_alpha_pass, is_alpha_pass;
@@ -1085,6 +1087,8 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
        GMS.lastretval = -1;
        GMS.lastalphablend = GPU_BLEND_SOLID;
 
+       GMS.backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING);
+
        GMS.gob = ob;
        GMS.gscene = scene;
        GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */
@@ -1248,6 +1252,13 @@ int GPU_enable_material(int nr, void *attribs)
                                alphablend= mat->game.alpha_blend;
 
                        if (GMS.is_alpha_pass) glDepthMask(1);
+
+                       if (GMS.backface_culling) {
+                               if(mat->game.flag)
+                                       glEnable(GL_CULL_FACE);
+                               else
+                                       glDisable(GL_CULL_FACE);
+                       }
                }
                else {
                        /* or do fixed function opengl material */
@@ -1283,6 +1294,9 @@ void GPU_disable_material(void)
        GMS.lastretval= 1;
 
        if (GMS.gboundmat) {
+               if (GMS.backface_culling)
+                       glDisable(GL_CULL_FACE);
+
                if (GMS.is_alpha_pass) glDepthMask(0);
                GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
                GMS.gboundmat= NULL;
index fb4d4202b31818b397d40d577e3713ce97cdbdd4..e89cc751a69024205715248cb2325e59bab6ce5d 100644 (file)
@@ -266,6 +266,7 @@ typedef struct View3D {
 #define V3D_SHOW_RECONSTRUCTION                128
 #define V3D_SHOW_CAMERAPATH            256
 #define V3D_SHOW_BUNDLENAME            512
+#define V3D_BACKFACE_CULLING   1024
 
 /* View3D->around */
 #define V3D_CENTER              0
index e4d380ef48cba056d19b9a7b73ae413c750e0cbc..9b4dcd03c79679e99fc6cedc430208bf364620b8 100644 (file)
@@ -1567,6 +1567,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Textured Solid", "Display face-assigned textures in solid view");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
+       prop = RNA_def_property(srna, "show_backface_culling", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_BACKFACE_CULLING);
+       RNA_def_property_ui_text(prop, "Backface Culling", "Use back face culling to hide the back side of faces");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
        prop = RNA_def_property(srna, "lock_camera", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_LOCK_CAMERA);
        RNA_def_property_ui_text(prop, "Lock Camera to View", "Enable view navigation within the camera view");