-First port of Displacement mapping from tuhopuu. Image textures not working
authorRobert Wenzlaff <rwenzlaff@soylent-green.com>
Mon, 5 Jan 2004 08:44:49 +0000 (08:44 +0000)
committerRobert Wenzlaff <rwenzlaff@soylent-green.com>
Mon, 5 Jan 2004 08:44:49 +0000 (08:44 +0000)
yet (R.vn and R.vlr no longer exist, and were needed to get the image mapped
right).  Works esp. well with Subsurfs. Sensitive to vertex normal issues
in Simple and Mesh modes.

-Also porting Simple Subdivide.  Subdivides mesh at rendertime w/o changing
shape, for smooth displace and Radiosity.

-Removed an unused var from KnifeSubdivide.

source/blender/blenkernel/intern/subsurf.c
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/render/extern/include/render_types.h
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_shading.c
source/blender/src/editmesh.c

index 4df97851fd9ba8d2458f622075fab5112be1bbb9..a7913c68a50c901d424c78b89e1e01bb7b985cdd 100644 (file)
@@ -610,6 +610,107 @@ static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) {
        }
 }
 
+/* Simple subdivition surface for radio and displacement */
+static void hypermesh_simple_subdivide(HyperMesh *me, HyperMesh *nme) {
+       HyperVert *v;
+       HyperEdge *e;
+       HyperFace *f;
+       LinkNode *link;
+       float co[3];
+       int j, k, count;
+
+       for (f= me->faces; f; f= f->next) { /* Adds vert at center of each existing face */
+               Vec3CpyI(co, 0.0, 0.0, 0.0);
+               for (j=0; j<f->nverts; j++)     Vec3Add(co, f->verts[j]->co);
+               Vec3MulN(co, (float)(1.0/f->nverts));
+
+               f->mid= hypermesh_add_vert(nme, co, NULL);
+       }
+               
+       for (e= me->edges; e; e= e->next) {  /* Add vert in middle of each edge */      
+               Vec3AvgT(co, e->v[0]->co, e->v[1]->co);
+               e->ep= hypermesh_add_vert(nme, co, NULL);
+       }
+
+       for (v= me->verts; v; v= v->next) {
+               v->nmv= hypermesh_add_vert(nme, v->co, v->orig);
+       }
+
+       for (e= me->edges; e; e= e->next) { /* Add originam edges */
+               hypermesh_add_edge(nme, e->v[0]->nmv, e->ep, e->flag);
+               hypermesh_add_edge(nme, e->v[1]->nmv, e->ep, e->flag);
+       }
+
+       for (f= me->faces; f; f= f->next) {
+               int last= f->nverts-1;
+               unsigned char vcol_mid[4];
+               unsigned char vcol_edge[4][4];
+               float uvco_mid[2];
+               float uvco_edge[4][4];
+               
+               if (me->hasvcol) {
+                       int t[4]= {0, 0, 0, 0};
+                       for (j=0; j<f->nverts; j++) {
+                               t[0]+= f->vcol[j][0];
+                               t[1]+= f->vcol[j][1];
+                               t[2]+= f->vcol[j][2];
+                               t[3]+= f->vcol[j][3];
+                       }
+                       vcol_mid[0]= t[0]/f->nverts;
+                       vcol_mid[1]= t[1]/f->nverts;
+                       vcol_mid[2]= t[2]/f->nverts;
+                       vcol_mid[3]= t[3]/f->nverts;
+                       
+                       for (j=0; j<f->nverts; last= j, j++)
+                               VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]);
+                       last= f->nverts-1;
+               }
+               if (me->hasuvco) {
+                       Vec2CpyI(uvco_mid, 0.0, 0.0);
+                       for (j=0; j<f->nverts; j++)
+                               Vec2Add(uvco_mid, f->uvco[j]);
+                       Vec2MulN(uvco_mid, (float)(1.0/f->nverts));
+
+                       for (j=0; j<f->nverts; last= j, j++)
+                               Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]);
+                       last= f->nverts-1;
+               }
+               
+               for (j=0; j<f->nverts; last=j, j++) {
+                       HyperVert *nv[4];
+                       HyperFace *nf;
+                       
+                       nv[0]= f->verts[last]->nmv;
+                       nv[1]= f->edges[j]->ep;
+                       nv[2]= f->mid;
+                       nv[3]= f->edges[last]->ep;
+                       
+                       nf= hypermesh_add_face(nme, nv, 4, 0);
+                       nf->orig= f->orig;
+                       
+                       if (me->hasvcol) {
+                               nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4);
+                               
+                               for (k=0; k<4; k++) {
+                                       nf->vcol[0][k]= f->vcol[last][k];
+                                       nf->vcol[1][k]= vcol_edge[j][k];
+                                       nf->vcol[2][k]= vcol_mid[k];
+                                       nf->vcol[3][k]= vcol_edge[last][k];
+                               }
+                       }
+                       if (me->hasuvco) {
+                               nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4);
+                               
+                               Vec2Cpy(nf->uvco[0], f->uvco[last]);
+                               Vec2Cpy(nf->uvco[1], uvco_edge[j]);
+                               Vec2Cpy(nf->uvco[2], uvco_mid);
+                               Vec2Cpy(nf->uvco[3], uvco_edge[last]);
+                       }
+               }
+       }
+}
+
+
 static void hypermesh_free(HyperMesh *me) {
        BLI_memarena_free(me->arena);
                        
@@ -914,9 +1015,10 @@ static DispList *subsurf_subdivide_to_displist(HyperMesh *hme, short subdiv, sho
                tmp->hasuvco= hme->hasuvco;
                tmp->orig_me= hme->orig_me;
                
-               hypermesh_subdivide(hme, tmp);
-               hypermesh_free(hme);
+               if (flag & ME_SIMPLE_DIV) hypermesh_simple_subdivide(hme, tmp);
+               else hypermesh_subdivide(hme, tmp);      /* default to CC subdiv. */
                
+               hypermesh_free(hme);
                hme= tmp;
        }
 
index f81f79f2b25a2a0fe8beceb783e1bbec00ad79d6..92642c634376fad4472105e07c596cef6d7cec93 100644 (file)
@@ -172,6 +172,7 @@ typedef struct Material {
 #define MAP_HAR                        256
 #define MAP_RAYMIRR            512
 #define MAP_TRANSLU            1024
+#define MAP_DISPLACE   4096
 
 /* pr_type */
 #define MA_FLAT                        0
index 3b69656464e0bea99d118ee59427b5147a581032..71c65d450bf3d4e4bad23d87007d747c598639fe 100644 (file)
@@ -165,6 +165,7 @@ typedef struct Mesh {
 #define ME_SMESH               64
 #define ME_SUBSURF             128
 #define ME_OPT_EDGES   256
+#define ME_SIMPLE_DIV   512
 
 /* puno = vertexnormal (mface) */
 #define ME_FLIPV1              1
index 7872e384079b0d994b50762236c98a25d81e80f9..ba95e2ecbedff014ce7fe6727383b6349795762d 100644 (file)
@@ -228,6 +228,7 @@ typedef struct Tex {
 #define MAP_ALPHA              128
 #define MAP_HAR                        256
 #define MAP_XTRA               512
+#define MAP_DISPLACE   4096
 
 /* pr_type */
 #define MA_FLAT                        0
index 90eb7c4f058d170b0114789ff4aff9b4c63762cc..536ce83a9ae2d3e76adbe79acab1010134ca1dd8 100644 (file)
@@ -159,6 +159,7 @@ typedef struct VertRen
        void *svert;                    /* smooth vert, only used during initrender */
        short clip, texofs;             /* texofs= flag */
        float accum;                    /* accum for radio weighting */
+       short flag;
 } VertRen;
 
 /* ------------------------------------------------------------------------- */
index 9bccd128a5c3c3dd060a49266951f2a39bbf0ed3..266194c5e014c78cbbc0f26d7a7bf161f98711f3 100644 (file)
@@ -144,6 +144,12 @@ static int test_flipnorm(float *v1, float *v2, float *v3, VlakRen *vlr, float im
 static void init_render_object(Object *ob);
 static HaloRen *initstar(float *vec, float hasize);
 
+/* Displacement Texture */
+void displace_render_face(VlakRen *vlr, int tex, float scale);
+void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert);
+short test_for_displace(Object *ob);
+void displace_render_vert(VertRen *vr, MTex *mtex, short mask, float scale);
+
 /* more prototypes for autosmoothing below */
 
 
@@ -1099,8 +1105,9 @@ static void init_render_displist_mesh(Object *ob)
        float xn, yn, zn;
        float mat[4][4], imat[3][3], *data, *nors, *orco=0, n1[3], flen;
        int a, b, flipnorm= -1,  need_orco=0, startvert, p1, p2, p3, p4;
-       int old_totvert= R.totvert;
-       int old_totvlak= R.totvlak;
+       int old_totvert= R.totvert, numvert=0;
+       int old_totvlak= R.totvlak, numface=0;
+       short displace_chanels=0;
 
        me= ob->data;
 
@@ -1123,6 +1130,9 @@ static void init_render_displist_mesh(Object *ob)
                }
        }
 
+       /* Test to see if there are displacement chanels */
+       displace_chanels=test_for_displace(ob);
+       
        dl= me->disp.first;
 
        /* Force a displist rebuild if this is a subsurf and we have a different subdiv level */
@@ -1147,7 +1157,7 @@ static void init_render_displist_mesh(Object *ob)
        while(dl) {
                if(dl->type==DL_SURF) {
                        startvert= R.totvert;
-                       a= dl->nr*dl->parts;
+                       numvert = a = dl->nr*dl->parts;
                        data= dl->verts;
                        nors= dl->nors;
                        
@@ -1195,6 +1205,7 @@ static void init_render_displist_mesh(Object *ob)
 
                                        flen= CalcNormFloat4(v1->co, v3->co, v4->co, v2->co, n1);
                                        if(flen!=0.0) {
+                                               numface++;
                                                vlr= RE_findOrAddVlak(R.totvlak++);
                                                vlr->ob= ob;
                                                vlr->v1= v1;
@@ -1233,6 +1244,8 @@ static void init_render_displist_mesh(Object *ob)
                        int i;
                        
                        startvert= R.totvert;
+                       numvert=dlm->totvert;
+                       
                        for (i=0; i<dlm->totvert; i++) {
                                MVert *mv= &dlm->mvert[i];
                                
@@ -1274,6 +1287,7 @@ static void init_render_displist_mesh(Object *ob)
                                }
 
                                if(flen!=0.0) {
+                                       numface++;
                                        vlr= RE_findOrAddVlak(R.totvlak++);
                                        vlr->ob= ob;
                                        vlr->v1= v1;
@@ -1310,8 +1324,11 @@ static void init_render_displist_mesh(Object *ob)
                
                dl= dl->next;
        }
-
-
+       
+       if (displace_chanels) {
+               do_displacement(ob, old_totvlak, numface, old_totvert, numvert );
+       }
+       
        normalenrender(old_totvert, old_totvlak);
 
 }
@@ -1510,7 +1527,9 @@ static void init_render_mesh(Object *ob)
        float *extverts=0, *orco;
        int a, a1, ok, do_puno, need_orco=0, totvlako, totverto, vertofs;
        int start, end, flipnorm, do_autosmooth=0;
-
+       short displace_chanels=0;
+       int startface, numface=0;
+       
        me= ob->data;
        if (rendermesh_uses_displist(me) && me->subdivr>0) {
                init_render_displist_mesh(ob);
@@ -1554,6 +1573,9 @@ static void init_render_mesh(Object *ob)
                }
        }
 
+       /* Test to see if there are displacement chanels */
+       displace_chanels=test_for_displace(ob);
+               
        if(me->orco==0) {
                need_orco= 0;
                for(a=1; a<=ob->totcol; a++) {
@@ -1767,6 +1789,11 @@ static void init_render_mesh(Object *ob)
                }
        }
        
+       if (displace_chanels) {
+               do_displacement(ob, totvlako, end, totverto, me->totvert );
+               do_puno=1;
+       }
+       
        if(do_autosmooth || (me->flag & ME_AUTOSMOOTH)) {
                autosmooth(totverto, totvlako, me->smoothresh);
                do_puno= 1;
@@ -3090,3 +3117,119 @@ void RE_rotateBlenderScene(void)
        set_normalflags();
 }
 
+
+/* **************************************************************** */
+/*                Displacement mapping                              */
+/* **************************************************************** */
+extern float Tin, Tr, Tg, Tb; 
+
+short test_for_displace(Object *ob){
+/* Produce bitfield indicating which textures are displacement textures. */
+       Material *ma;
+       short result = 0; 
+       int i, j;
+       
+       for (i=1; i<=ob->totcol; i++) {
+               ma=give_render_material(ob, i);
+               if (ma) for(j=0; j<8; j++){
+                       if (ma->mtex[j] && (ma->mtex[j]->mapto & MAP_DISPLACE)){
+                               result |= 1<<j;
+                       }
+               }
+       }
+       return result;
+}
+
+
+void do_displacement(Object *ob, int startface, int numface, int startvert, int numvert ){
+
+       int i, j;
+       Material *ma; 
+       MTex *mtex;
+       float co[3]={0,0,0}, min[3]={1e9, 1e9, 1e9}, max[3]={-1e9, -1e9, -1e9};
+       float scale=1.0f;
+       VertRen *vr;
+       VlakRen *vlr;
+       Mesh *me;
+       
+       minmax_object(ob, min, max);
+       VecSubf(min, max, min);
+       scale=MAX3(min[0], min[1], min[2]); /*Overall scale of obj */
+       
+       /* calculate vertex normals */
+       //normalenrender(startvert, startface);
+       
+       for(i=startvert; i<startvert+numvert; i++){ /* Clear vert flags */
+               vr=RE_findOrAddVert(i);
+               vr->flag=0;
+       }
+       
+       for(i=startface; i<startface+numface; i++){
+               vlr=RE_findOrAddVlak(i);
+
+               for(j=0; j<8; j++){
+                       mtex = vlr->mat->mtex[j];
+                       if ((mtex)&&( vlr->mat->mtex[j]->mapto & MAP_DISPLACE ) ) displace_render_face(vlr, j, scale);
+               }       
+               
+               /* Recaluclate the face normal */
+               if(vlr->v4) vlr->len= CalcNormFloat4(vlr->v4->co, vlr->v3->co, vlr->v2->co,
+                                                           vlr->v1->co, vlr->n);
+               else vlr->len= CalcNormFloat(vlr->v3->co, vlr->v2->co, vlr->v1->co,
+                                                           vlr->n);
+               
+       }
+}
+
+void displace_render_face(VlakRen *vlr, int tex, float scale){
+
+       MTex *mtex;
+       int mask;
+       float dp;
+       
+       VlakRen vlr2; 
+       VertRen vr;
+
+       mask = 1<<tex; /* Displace vert once per displace texture channel */
+       mtex=vlr->mat->mtex[tex];
+       
+       //VECCOPY(R.vn, vlr->n);        /* extertex() needs face/puno */
+       //R.vlr=vlr;
+       
+       /* Displace the verts */
+       
+       if (! (vlr->v1->flag & mask)) displace_render_vert(vlr->v1, mtex, mask, scale);
+       
+       if (! (vlr->v2->flag & mask) ) displace_render_vert(vlr->v2, mtex, mask, scale);
+       
+       if (! (vlr->v3->flag & mask)) displace_render_vert(vlr->v3, mtex, mask, scale);
+                       
+       if (vlr->v4) {
+               if (!(vlr->v4->flag & mask)) displace_render_vert(vlr->v4, mtex, mask, scale);
+       }
+}
+
+void displace_render_vert(VertRen *vr, MTex *mtex, short mask, float scale){
+
+       float co[3]={0,0,0}, dp, sample[3];
+
+       if ((mtex->texco & TEXCO_ORCO) && (vr->orco)) {
+               VECCOPY(co, vr->orco);
+       }
+       else if ((mtex->texco & TEXCO_STICKY) && (vr->sticky)) {
+               VECCOPY(co, vr->sticky);
+       }
+       else if (mtex->texco & TEXCO_GLOB) {
+                /* VECCOPY(co, vr->co);  Interesting, but not right. */
+                
+       }
+       
+       externtex(mtex, co);
+
+       vr->co[0]+=0.25*(Tin-0.5) * vr->n[0] * mtex->varfac *scale ; 
+       vr->co[1]+=0.25*(Tin-0.5) * vr->n[1] * mtex->varfac *scale ;
+       vr->co[2]+=0.25*(Tin-0.5) * vr->n[2] * mtex->varfac *scale ; 
+       
+       vr->flag |= mask;
+
+}
index 4197a80d1f81a4a5face69a7383f0b45ce907800..ee7679a478bd68e855637b51db56af91ee1dc3ca 100644 (file)
@@ -379,7 +379,8 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me)
        
        uiBlockBeginAlign(block);
        uiBlockSetCol(block, TH_BUT_SETTING1);
-       uiDefButS(block, TOG|BIT|7, B_MAKEDISP, "SubSurf",              10,124,154,19, &me->flag, 0, 0, 0, 0, "Treats the active object as a Catmull-Clark Subdivision Surface");
+       uiDefButS(block, TOG|BIT|7, B_MAKEDISP, "SubSurf",              10,124,90,19, &me->flag, 0, 0, 0, 0, "Treats the active object as a Catmull-Clark Subdivision Surface");
+       uiDefButS(block, TOG|BIT|9, B_MAKEDISP, "Simple",               100,124,64,19, &me->flag, 0, 0, 0, 0, "Treats the active object as a Simple Subdivision Surface for Radio/Displacement");
        uiBlockSetCol(block, TH_AUTO);
        uiDefButS(block, NUM, B_MAKEDISP, "Subdiv:",                    10,104,110,19, &me->subdiv, 0, 6, 0, 0, "Defines the level of subdivision to display in real time interactively");
        uiDefButS(block, NUM, B_MAKEDISP, "",                                   120, 104, 44, 19, &me->subdivr, 0, 6, 0, 0, "Defines the level of subdivision to apply during rendering");
index 87a85d1bf1919ef87ea51f480d8eb38f17260e53..a10dea000b815d7ea5c4bc4dc0eb4dc35aecdd18 100644 (file)
@@ -2118,18 +2118,19 @@ static void material_panel_map_to(Material *ma)
        
        /* MAP TO */
        uiBlockBeginAlign(block);
-       uiDefButS(block, TOG|BIT|0, B_MATPRV, "Col",    900,180,73,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic colour of the material");
-       uiDefButS(block, TOG3|BIT|1, B_MATPRV, "Nor",   973,180,73,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
-       uiDefButS(block, TOG|BIT|2, B_MATPRV, "Csp",    1046,180,73,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity colour");
-       uiDefButS(block, TOG|BIT|3, B_MATPRV, "Cmir",   1119,180,73,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affext the mirror colour");
-       uiDefButS(block, TOG3|BIT|4, B_MATPRV, "Ref",   1192,180,74,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of the materials reflectivity");
-
-       uiDefButS(block, TOG3|BIT|5, B_MATPRV, "Spec",  900,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of specularity");
-       uiDefButS(block, TOG3|BIT|8, B_MATPRV, "Hard",  960,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the hardness value");
-       uiDefButS(block, TOG3|BIT|9, B_MATPRV, "RayMir",1020,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
-       uiDefButS(block, TOG3|BIT|7, B_MATPRV, "Alpha", 1080,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
-       uiDefButS(block, TOG3|BIT|6, B_MATPRV, "Emit",  1140,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
-       uiDefButS(block, TOG3|BIT|10, B_MATPRV, "Translu",1200,160,63,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the translucency value");
+       uiDefButS(block, TOG|BIT|0, B_MATPRV, "Col",    900,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic colour of the material");
+       uiDefButS(block, TOG3|BIT|1, B_MATPRV, "Nor",   960,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal");
+       uiDefButS(block, TOG|BIT|2, B_MATPRV, "Csp",    1020,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity colour");
+       uiDefButS(block, TOG|BIT|3, B_MATPRV, "Cmir",   1080,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affext the mirror colour");
+       uiDefButS(block, TOG3|BIT|4, B_MATPRV, "Ref",   1140,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of the materials reflectivity");
+       uiDefButS(block, TOG3|BIT|5, B_MATPRV, "Spec",  1200,180,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of specularity");
+       
+       uiDefButS(block, TOG3|BIT|8, B_MATPRV, "Hard",  900,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the hardness value");
+       uiDefButS(block, TOG3|BIT|9, B_MATPRV, "RayMir",960,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the ray-mirror value");
+       uiDefButS(block, TOG3|BIT|7, B_MATPRV, "Alpha", 1020,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the alpha value");
+       uiDefButS(block, TOG3|BIT|6, B_MATPRV, "Emit",  1080,160,60,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the emit value");
+       uiDefButS(block, TOG3|BIT|10, B_MATPRV, "Translu",1140,160,65,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the translucency value");
+       uiDefButS(block, TOG|BIT|12, B_MATPRV, "Disp",  1205,160,55,19, &(mtex->mapto), 0, 0, 0, 0, "Let the texture displace the surface");
        
        uiBlockBeginAlign(block);
        uiDefButS(block, ROW, B_MATPRV, "Mix",                  1087,120,48,18, &(mtex->blendtype), 9.0, (float)MTEX_BLEND, 0, 0, "Sets texture to blend the values or colour");
index 68d23189863165cd39d84252c6232d5ea77acc76..0d0cecfa71706903bf3db8184ba9380e454b89f3 100644 (file)
@@ -7410,7 +7410,7 @@ CutCurve *get_mouse_trail(int *len, char mode){
 void KnifeSubdivide(char mode){
 
        int oldcursor, len=0;
-       short isect=0, aligned=0;
+       short isect=0;
        CutCurve *curve;                
        EditEdge *eed; 
        Window *win;