Merged changes in the trunk up to revision 46045.
[blender-staging.git] / source / blender / render / intern / source / convertblender.c
index 7fe1fab1681ddaacf6bd16b3f44e6ce501b7e812..8013251fb3ce1631a8746f9c368889a16545581e 100644 (file)
@@ -42,6 +42,7 @@
 #include "BLI_rand.h"
 #include "BLI_memarena.h"
 #include "BLI_ghash.h"
+#include "BLI_edgehash.h"
 
 #include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
@@ -2743,7 +2744,7 @@ static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr,
                                        v2= mface->v2;
                                        v3= mface->v3;
                                        v4= mface->v4;
-                                       flag= mface->flag & ME_SMOOTH;
+                                       flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE);
 
                                        vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                                        vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3247,6 +3248,24 @@ static void add_volume(Render *re, ObjectRen *obr, Material *ma)
        BLI_addtail(&re->volumes, vo);
 }
 
+static EdgeHash *make_freestyle_edge_mark_hash(MEdge *medge, int totedge)
+{
+       EdgeHash *edge_hash= BLI_edgehash_new();
+       int a;
+
+       for(a=0; a<totedge; a++) {
+               if(medge[a].flag & ME_FREESTYLE_EDGE)
+                       BLI_edgehash_insert(edge_hash, medge[a].v1, medge[a].v2, medge+a);
+       }
+       return edge_hash;
+}
+
+static int has_freestyle_edge_mark(EdgeHash *edge_hash, int v1, int v2)
+{
+       MEdge *medge= BLI_edgehash_lookup(edge_hash, v1, v2);
+       return (!medge) ? 0 : 1;
+}
+
 static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 {
        Object *ob= obr->ob;
@@ -3374,6 +3393,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                }
                
                if (!timeoffset) {
+                       EdgeHash *edge_hash;
+                       MEdge *medge;
+                       int totedge;
+
+                       /* create a hash table of Freestyle edge marks */
+                       medge= dm->getEdgeArray(dm);
+                       totedge= dm->getNumEdges(dm);
+                       edge_hash= make_freestyle_edge_mark_hash(medge, totedge);
+
                        /* store customdata names, because DerivedMesh is freed */
                        RE_set_customdata_names(obr, &dm->faceData);
 
@@ -3416,13 +3444,15 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                                                
                                                if ( mface->mat_nr==a1 ) {
                                                        float len;
+                                                       int edge_mark= 0;
+                                                               
                                                        int reverse_verts = negative_scale!=0 && do_autosmooth==0;
                                                        int rev_tab[] = {reverse_verts==0 ? 0 : 2, 1, reverse_verts==0 ? 2 : 0, 3};
                                                        v1= reverse_verts==0 ? mface->v1 : mface->v3;
                                                        v2= mface->v2;
                                                        v3= reverse_verts==0 ? mface->v3 : mface->v1;
                                                        v4= mface->v4;
-                                                       flag= mface->flag & ME_SMOOTH;
+                                                       flag= mface->flag & (ME_SMOOTH | ME_FREESTYLE_FACE);
 
                                                        vlr= RE_findOrAddVlak(obr, obr->totvlak++);
                                                        vlr->v1= RE_findOrAddVert(obr, vertofs+v1);
@@ -3431,6 +3461,17 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                                                        if (v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4);
                                                        else vlr->v4= 0;
 
+                                                       /* Freestyle edge marks */
+                                                       if(has_freestyle_edge_mark(edge_hash, v1, v2)) edge_mark |= R_EDGE_V1V2;
+                                                       if(has_freestyle_edge_mark(edge_hash, v2, v3)) edge_mark |= R_EDGE_V2V3;
+                                                       if (!v4) {
+                                                               if(has_freestyle_edge_mark(edge_hash, v3, v1)) edge_mark |= R_EDGE_V3V1;
+                                                       } else {
+                                                               if(has_freestyle_edge_mark(edge_hash, v3, v4)) edge_mark |= R_EDGE_V3V4;
+                                                               if(has_freestyle_edge_mark(edge_hash, v4, v1)) edge_mark |= R_EDGE_V4V1;
+                                                       }
+                                                       vlr->freestyle_edge_mark= edge_mark;
+
                                                        /* render normals are inverted in render */
                                                        if (use_original_normals) {
                                                                MFace *mf= me->mface+a;
@@ -3497,6 +3538,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
                                        }
                                }
                        }
+
+                       /* release the hash table of Freestyle edge marks */
+                       BLI_edgehash_free(edge_hash, NULL);
                        
                        /* exception... we do edges for wire mode. potential conflict when faces exist... */
                        end= dm->getNumEdges(dm);
@@ -4283,6 +4327,23 @@ static void check_non_flat_quads(ObjectRen *obr)
                                        /* new normals */
                                        normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co);
                                        normal_tri_v3( vlr1->n,vlr1->v3->co, vlr1->v2->co, vlr1->v1->co);
+
+                                       /* Freestyle edge marks */
+                                       if (vlr->flag & R_DIVIDE_24) {
+                                               vlr1->freestyle_edge_mark=
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V1V2 : 0) |
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0);
+                                               vlr->freestyle_edge_mark=
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+                                       } else {
+                                               vlr1->freestyle_edge_mark=
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V3V4) ? R_EDGE_V2V3 : 0) |
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V4V1) ? R_EDGE_V3V1 : 0);
+                                               vlr->freestyle_edge_mark=
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V1V2) ? R_EDGE_V1V2 : 0) |
+                                                       ((vlr->freestyle_edge_mark & R_EDGE_V2V3) ? R_EDGE_V2V3 : 0);
+                                       }
                                }
                                /* clear the flag when not divided */
                                else vlr->flag &= ~R_DIVIDE_24;