Long waited feature: Render Baking
authorTon Roosendaal <ton@blender.org>
Sun, 19 Nov 2006 14:12:56 +0000 (14:12 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 19 Nov 2006 14:12:56 +0000 (14:12 +0000)
Here's the full release log with example file.
http://www.blender3d.org/cms/Render_Baking.827.0.html

For people who don't read docs; just press ALT+CTRL+B on a Mesh
with texture faces!

Todos:
- maybe some filter options extra?
- Make normal maps in Tangent space

15 files changed:
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/displist.c
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/intern/filter.c
source/blender/include/BIF_meshtools.h
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/zbuf.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/ray.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/zbuf.c
source/blender/src/header_info.c
source/blender/src/meshtools.c
source/blender/src/space.c

index 18b59a751338bf1804a9062fbc764e32b0a4b99f..824c1566100fd8950578b068b06629d28c5f3bee 100644 (file)
@@ -240,7 +240,7 @@ void RE_FreeRender(Render *re) {}
 void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr) {}
 void RE_DataBase_GetView(Render *re, float mat[][4]) {}
 struct Render *RE_NewRender(const char *name) {return (struct Render *)NULL;}
 void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr) {}
 void RE_DataBase_GetView(Render *re, float mat[][4]) {}
 struct Render *RE_NewRender(const char *name) {return (struct Render *)NULL;}
-void RE_Database_Shaded(struct Render *re, struct Scene *scene) {};
+void RE_Database_Baking(struct Render *re, struct Scene *scene, int make_faces) {};
 
 /* node_composite.c */
 void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) {}
 
 /* node_composite.c */
 void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) {}
index 4ac3ea2aac2d3ede1a3dac8ecfe501c1f72a0f77..5e3439da6bff670c3ddcc044354839c28d89b507 100644 (file)
@@ -377,7 +377,7 @@ static Render *fastshade_get_render(void)
        if(re==NULL) {
                re= RE_NewRender("_Shade View_");
        
        if(re==NULL) {
                re= RE_NewRender("_Shade View_");
        
-               RE_Database_Shaded(re, G.scene);
+               RE_Database_Baking(re, G.scene, 0);     /* 0= no faces */
        }
        return re;
 }
        }
        return re;
 }
@@ -393,7 +393,7 @@ void fastshade_free_render(void)
        }
 }
 
        }
 }
 
-static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol)
+static void fastshade(float *co, float *nor, float *orco, float *uv, Material *ma, char *col1, char *col2, char *vertcol)
 {
        ShadeResult shr;
        int a;
 {
        ShadeResult shr;
        int a;
@@ -409,6 +409,7 @@ static void fastshade(float *co, float *nor, float *orco, Material *ma, char *co
        shi.vn[1]= -nor[1];
        shi.vn[2]= -nor[2];
        VECCOPY(shi.vno, shi.vn);
        shi.vn[1]= -nor[1];
        shi.vn[2]= -nor[2];
        VECCOPY(shi.vno, shi.vn);
+       VECCOPY(shi.facenor, shi.vn);
        
        if(ma->texco) {
                VECCOPY(shi.lo, orco);
        
        if(ma->texco) {
                VECCOPY(shi.lo, orco);
@@ -423,7 +424,13 @@ static void fastshade(float *co, float *nor, float *orco, Material *ma, char *co
                        VECCOPY(shi.sticky, shi.lo);
                }
                if(ma->texco & TEXCO_UV) {
                        VECCOPY(shi.sticky, shi.lo);
                }
                if(ma->texco & TEXCO_UV) {
-                       VECCOPY(shi.uv, shi.lo);
+                       if(uv) {
+                               shi.uv[0]= 2.0f*uv[0]-1.0f;
+                               shi.uv[1]= 2.0f*uv[1]-1.0f;
+                       }
+                       else {
+                               VECCOPY(shi.uv, shi.lo);
+                       }
                }
                if(ma->texco & TEXCO_OBJECT) {
                        VECCOPY(shi.co, shi.lo);
                }
                if(ma->texco & TEXCO_OBJECT) {
                        VECCOPY(shi.co, shi.lo);
@@ -567,11 +574,12 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
 
        for (i=0; i<dlm->totface; i++) {
                MFace *mf= &dlm->mface[i];
 
        for (i=0; i<dlm->totface; i++) {
                MFace *mf= &dlm->mface[i];
+               TFace *tface= dlm->tface?&dlm->tface[i]:NULL;
+               Material *ma= give_current_material(ob, mf->mat_nr+1);
                int j, vidx[4], nverts= mf->v4?4:3;
                unsigned char *col1base= (unsigned char*) &col1[i*4];
                unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
                unsigned char *mcolbase;
                int j, vidx[4], nverts= mf->v4?4:3;
                unsigned char *col1base= (unsigned char*) &col1[i*4];
                unsigned char *col2base= (unsigned char*) (col2?&col2[i*4]:NULL);
                unsigned char *mcolbase;
-               Material *ma= give_current_material(ob, mf->mat_nr+1);
                float nor[3], n1[3];
                
                if(ma==NULL) ma= &defmaterial;
                float nor[3], n1[3];
                
                if(ma==NULL) ma= &defmaterial;
@@ -609,10 +617,14 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
                        char *col2= (char*)(col2base?&col2base[j*4]:NULL);
                        char *mcol= (char*)(mcolbase?&mcolbase[j*4]:NULL);
                        float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
                        char *col2= (char*)(col2base?&col2base[j*4]:NULL);
                        char *mcol= (char*)(mcolbase?&mcolbase[j*4]:NULL);
                        float *vn = (mf->flag & ME_SMOOTH)?&vnors[3*vidx[j]]:n1;
-
+                       float *uv= tface?tface->uv[j]:NULL;
+                       
                        VECCOPY(vec, mv->co);
                        Mat4MulVecfl(mat, vec);
                        VECCOPY(vec, mv->co);
                        Mat4MulVecfl(mat, vec);
-                       fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2, mcol);
+                       vec[0]+= 0.001*vn[0];
+                       vec[1]+= 0.001*vn[1];
+                       vec[2]+= 0.001*vn[2];
+                       fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, uv, ma, col1, col2, mcol);
                }
        } 
        MEM_freeN(vnors);
                }
        } 
        MEM_freeN(vnors);
@@ -705,7 +717,7 @@ void shadeDispList(Base *base)
                                                        VECCOPY(vec, fp);
                                                        Mat4MulVecfl(mat, vec);
                                                        
                                                        VECCOPY(vec, fp);
                                                        Mat4MulVecfl(mat, vec);
                                                        
-                                                       fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+                                                       fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL);
                                                        
                                                        fp+= 3; col1++;
                                                }
                                                        
                                                        fp+= 3; col1++;
                                                }
@@ -726,7 +738,7 @@ void shadeDispList(Base *base)
                                                        n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
                                                        Normalise(n1);
                                
                                                        n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
                                                        Normalise(n1);
                                
-                                                       fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+                                                       fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL);
                                                        
                                                        fp+= 3; nor+= 3; col1++;
                                                }
                                                        
                                                        fp+= 3; nor+= 3; col1++;
                                                }
@@ -764,7 +776,7 @@ void shadeDispList(Base *base)
                                                        n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
                                                        Normalise(n1);
                                                
                                                        n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2];
                                                        Normalise(n1);
                                                
-                                                       fastshade(vec, n1, fp, ma, (char *)col1, 0, 0);
+                                                       fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL);
                                                        
                                                        fp+= 3; col1++; nor+= 3;
                                                }
                                                        
                                                        fp+= 3; col1++; nor+= 3;
                                                }
index 79d2d148c19f60dd75d0c1ad466629831cc7d0f7..02b3557c094e62cd2f1d3eee2ec21867aac6cc92 100644 (file)
@@ -314,6 +314,7 @@ void IMB_antialias(struct ImBuf * ibuf);
  */
 void IMB_filter(struct ImBuf *ibuf);
 void IMB_filterN(struct ImBuf *out, struct ImBuf *in);
  */
 void IMB_filter(struct ImBuf *ibuf);
 void IMB_filterN(struct ImBuf *out, struct ImBuf *in);
+void IMB_filter_extend(struct ImBuf *ibuf);
 
 /**
  *
 
 /**
  *
index 8c5bc430aea008275b4d949d3e5d39419df1bb6e..343211eb6b0e9dc9ce09b2fc5506514c5c93406a 100644 (file)
@@ -132,27 +132,27 @@ void IMB_filtery(struct ImBuf *ibuf)
 {
        unsigned char *point;
        float *pointf;
 {
        unsigned char *point;
        float *pointf;
-       int x, y, skip, do_float = 0;
+       int x, y, skip;
 
        point = (unsigned char *)ibuf->rect;
        pointf = ibuf->rect_float;
 
 
        point = (unsigned char *)ibuf->rect;
        pointf = ibuf->rect_float;
 
-       if (ibuf->rect_float != NULL) do_float = 1;
-
        x = ibuf->x;
        y = ibuf->y;
        skip = x<<2;
 
        for (;x>0;x--){
        x = ibuf->x;
        y = ibuf->y;
        skip = x<<2;
 
        for (;x>0;x--){
-               if (ibuf->depth > 24) filtcolum(point,y,skip);
-               point++;
-               filtcolum(point,y,skip);
-               point++;
-               filtcolum(point,y,skip);
-               point++;
-               filtcolum(point,y,skip);
-               point++;
-               if (do_float) {
+               if (point) {
+                       if (ibuf->depth > 24) filtcolum(point,y,skip);
+                       point++;
+                       filtcolum(point,y,skip);
+                       point++;
+                       filtcolum(point,y,skip);
+                       point++;
+                       filtcolum(point,y,skip);
+                       point++;
+               }
+               if (pointf) {
                        if (ibuf->depth > 24) filtcolumf(pointf,y,skip);
                        pointf++;
                        filtcolumf(pointf,y,skip);
                        if (ibuf->depth > 24) filtcolumf(pointf,y,skip);
                        pointf++;
                        filtcolumf(pointf,y,skip);
@@ -170,27 +170,27 @@ void imb_filterx(struct ImBuf *ibuf)
 {
        unsigned char *point;
        float *pointf;
 {
        unsigned char *point;
        float *pointf;
-       int x, y, skip, do_float =0;
+       int x, y, skip;
 
        point = (unsigned char *)ibuf->rect;
        pointf = ibuf->rect_float;
 
 
        point = (unsigned char *)ibuf->rect;
        pointf = ibuf->rect_float;
 
-       if (ibuf->rect_float != NULL) do_float = 1;
-
        x = ibuf->x;
        y = ibuf->y;
        skip = (x<<2) - 3;
 
        for (;y>0;y--){
        x = ibuf->x;
        y = ibuf->y;
        skip = (x<<2) - 3;
 
        for (;y>0;y--){
-               if (ibuf->depth > 24) filtrow(point,x);
-               point++;
-               filtrow(point,x);
-               point++;
-               filtrow(point,x);
-               point++;
-               filtrow(point,x);
-               point+=skip;
-               if (do_float) {
+               if (point) {
+                       if (ibuf->depth > 24) filtrow(point,x);
+                       point++;
+                       filtrow(point,x);
+                       point++;
+                       filtrow(point,x);
+                       point++;
+                       filtrow(point,x);
+                       point+=skip;
+               }
+               if (pointf) {
                        if (ibuf->depth > 24) filtrowf(pointf,x);
                        pointf++;
                        filtrowf(pointf,x);
                        if (ibuf->depth > 24) filtrowf(pointf,x);
                        pointf++;
                        filtrowf(pointf,x);
@@ -239,3 +239,66 @@ void IMB_filter(struct ImBuf *ibuf)
        IMB_filtery(ibuf);
        imb_filterx(ibuf);
 }
        IMB_filtery(ibuf);
        imb_filterx(ibuf);
 }
+
+#define EXTEND_PIXEL(a, w)     if((a)[3]) {r+= w*(a)[0]; g+= w*(a)[1]; b+= w*(a)[2]; tot+=w;}
+
+/* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 255 */
+void IMB_filter_extend(struct ImBuf *ibuf)
+{
+       register char *row1, *row2, *row3;
+       register char *cp;
+       int rowlen, x, y;
+       
+       rowlen= ibuf->x;
+       
+       if(ibuf->rect) {
+               int *temprect;
+               
+               /* make a copy, to prevent flooding */
+               temprect= MEM_dupallocN(ibuf->rect);
+               
+               for(y=1; y<=ibuf->y; y++) {
+                       /* setup rows */
+                       row1= (char *)(temprect + (y-2)*rowlen);
+                       row2= row1 + 4*rowlen;
+                       row3= row2 + 4*rowlen;
+                       if(y==1)
+                               row1= row2;
+                       else if(y==ibuf->y)
+                               row3= row2;
+                       
+                       cp= (char *)(ibuf->rect + (y-1)*rowlen);
+                       
+                       for(x=0; x<rowlen; x++) {
+                               if(cp[3]==0) {
+                                       int tot= 0, r=0, g=0, b=0;
+                                       
+                                       EXTEND_PIXEL(row1, 1);
+                                       EXTEND_PIXEL(row2, 2);
+                                       EXTEND_PIXEL(row3, 1);
+                                       EXTEND_PIXEL(row1+4, 2);
+                                       EXTEND_PIXEL(row3+4, 2);
+                                       if(x!=rowlen-1) {
+                                               EXTEND_PIXEL(row1+8, 1);
+                                               EXTEND_PIXEL(row2+8, 2);
+                                               EXTEND_PIXEL(row3+8, 1);
+                                       }                                       
+                                       if(tot) {
+                                               cp[0]= r/tot;
+                                               cp[1]= g/tot;
+                                               cp[2]= b/tot;
+                                               cp[3]= 255;
+                                       }
+                               }
+                               cp+=4; 
+                               
+                               if(x!=0) {
+                                       row1+=4; row2+=4; row3+=4;
+                               }
+                       }
+               }
+               
+               MEM_freeN(temprect);
+       }
+}
+
index e926d41faf141e3cd13b1abb27daf98631836cda..166dd4542b5594fd9cc3ce3e86d5cffefa282835 100644 (file)
@@ -42,6 +42,7 @@ extern void fasterdraw(void);
 extern void slowerdraw(void);
 
 extern void sort_faces(void);
 extern void slowerdraw(void);
 
 extern void sort_faces(void);
+extern void objects_bake_render(void);
 
 extern long mesh_octree_table(struct Object *ob, float *co, char mode);
 extern int mesh_get_x_mirror_vert(struct Object *ob, int index);
 
 extern long mesh_octree_table(struct Object *ob, float *co, char mode);
 extern int mesh_get_x_mirror_vert(struct Object *ob, int index);
index eed13e15ed556c57d36c920ae273fee744a6577d..d423b8117b1f8645d0f4b5671428c67cffd86849 100644 (file)
@@ -187,8 +187,13 @@ float RE_filter_value(int type, float x);
 /* vector blur zbuffer method */
 void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect);
 
 /* vector blur zbuffer method */
 void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect);
 
-/* shaded view options */
-void RE_Database_Shaded(struct Render *re, struct Scene *scene);
+/* shaded view or baking options */
+#define RE_BAKE_LIGHT  0
+#define RE_BAKE_ALL            1
+#define RE_BAKE_AO             2
+#define RE_BAKE_NORMALS        3
+void RE_Database_Baking(struct Render *re, struct Scene *scene, int type);
+
 void RE_DataBase_GetView(struct Render *re, float mat[][4]);
 
 #endif /* RE_PIPELINE_H */
 void RE_DataBase_GetView(struct Render *re, float mat[][4]);
 
 #endif /* RE_PIPELINE_H */
index 25110e4edfbd9e0502532d3e630363450b98584c..c135f7ac023db56a4795a1d397e8821b6977e798 100644 (file)
@@ -115,10 +115,10 @@ typedef struct ShadeInput
 struct Tex;
 int    multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres);
 
 struct Tex;
 int    multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres);
 
-/* shaded view */
+/* shaded view and bake */
 struct Render;
 void RE_shade_external(struct Render *re, struct ShadeInput *shi, struct ShadeResult *shr);
 struct Render;
 void RE_shade_external(struct Render *re, struct ShadeInput *shi, struct ShadeResult *shr);
-
+void RE_bake_shade_all_selected(struct Render *re, int type);
 
 #endif /* RE_SHADER_EXT_H */
 
 
 #endif /* RE_SHADER_EXT_H */
 
index cd8ad8626db617451600ab59900ab4083ca614ac..993ca711a18c0d982914aee1386375d7e37a0661 100644 (file)
@@ -95,6 +95,9 @@ typedef struct ZSpan {
 void zbufclip4(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4);
 void zbuf_free_span(struct ZSpan *zspan);
 
 void zbufclip4(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, float *f4, int c1, int c2, int c3, int c4);
 void zbuf_free_span(struct ZSpan *zspan);
 
+/* to rendercore.c */
+void zspan_scanconvert(struct ZSpan *zpan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) );
+
 /* exported to edge render... */
 void zbufclip(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3);
 void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty);
 /* exported to edge render... */
 void zbufclip(struct ZSpan *zspan, int zvlnr, float *f1, float *f2, float *f3, int c1, int c2, int c3);
 void zbuf_alloc_span(struct ZSpan *zspan, int rectx, int recty);
index c294eea48969a97ffec2fe3cd4bc36832344df49..42eb3c4715509b75acd2961604e2370d4ec53260 100644 (file)
@@ -3892,17 +3892,38 @@ void RE_DataBase_ApplyWindow(Render *re)
        project_renderdata(re, projectverto, 0, 0);
 }
 
        project_renderdata(re, projectverto, 0, 0);
 }
 
-/* setup for shaded view, so only lamps and materials are initialized */
-void RE_Database_Shaded(Render *re, Scene *scene)
+/* setup for shaded view or bake, so only lamps and materials are initialized */
+/* type:
+   RE_BAKE_LIGHT:  for shaded view, only add lamps
+   RE_BAKE_ALL:    for baking, all lamps and objects
+   RE_BAKE_NORMALS:for baking, no lamps and only selected objects
+   RE_BAKE_AO: for baking, no lamps, but all objects
+*/
+void RE_Database_Baking(Render *re, Scene *scene, int type)
 {
        Base *base;
        Object *ob;
        Scene *sce;
 {
        Base *base;
        Object *ob;
        Scene *sce;
+       GroupObject *go;
        float mat[4][4];
        unsigned int lay;
        
        re->scene= scene;
        
        float mat[4][4];
        unsigned int lay;
        
        re->scene= scene;
        
+       /* renderdata setup and exceptions */
+       re->r= scene->r;
+       re->r.mode &= ~R_OSA;
+       
+       if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS) ) {
+               re->r.mode &= ~R_SHADOW;
+               re->r.mode &= ~R_RAYTRACE;
+       }
+       
+       /* setup render stuff */
+       if(type!=RE_BAKE_LIGHT)
+               re->memArena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+       
+       re->totvlak=re->totvert=re->totlamp=re->tothalo= 0;
        re->lights.first= re->lights.last= NULL;
 
        /* in localview, lamps are using normal layers, objects only local bits */
        re->lights.first= re->lights.last= NULL;
 
        /* in localview, lamps are using normal layers, objects only local bits */
@@ -3920,9 +3941,18 @@ void RE_Database_Shaded(Render *re, Scene *scene)
                RE_SetView(re, mat);
        }
        
                RE_SetView(re, mat);
        }
        
-       /* initializes global */
+       init_render_world(re);  /* do first, because of ambient. also requires re->osa set correct */
+       if( (re->wrld.mode & WO_AMB_OCC) && (re->r.mode & R_RAYTRACE) ) {
+               re->wrld.aosphere= MEM_mallocN(2*3*re->wrld.aosamp*re->wrld.aosamp*sizeof(float), "AO sphere");
+               /* we make twice the amount of samples, because only a hemisphere is used */
+               init_ao_sphere(re->wrld.aosphere, 2*re->wrld.aosamp*re->wrld.aosamp, 16);
+       }
+       
+       /* still bad... doing all */
+       init_render_textures(re);
+       init_render_materials(re->osa, &re->wrld.ambr);
        set_node_shader_lamp_loop(shade_material_loop);
        set_node_shader_lamp_loop(shade_material_loop);
-
+       
        for(SETLOOPER(re->scene, base)) {
                ob= base->object;
                /* imat objects has to be done here, since displace can have texture using Object map-input */
        for(SETLOOPER(re->scene, base)) {
                ob= base->object;
                /* imat objects has to be done here, since displace can have texture using Object map-input */
@@ -3938,13 +3968,46 @@ void RE_Database_Shaded(Render *re, Scene *scene)
                
                /* OB_DONE means the object itself got duplicated, so was already converted */
                if(ob->flag & OB_DONE);
                
                /* OB_DONE means the object itself got duplicated, so was already converted */
                if(ob->flag & OB_DONE);
-               else if(ob->type==OB_LAMP) {
-                       if( (base->lay & lay) || ((base->lay & re->scene->lay)) ) {
-                               init_render_object(re, ob, NULL, 0, 0);
+               else if( (base->lay & lay) || ((base->lay & re->scene->lay)) ) {
+                       if(ob->type==OB_LAMP) {
+                               if(type!=RE_BAKE_NORMALS && type!=RE_BAKE_AO)
+                                       init_render_object(re, ob, NULL, 0, 0);
+                       }
+                       else if(type!=RE_BAKE_LIGHT) {
+                               if(type!=RE_BAKE_NORMALS || (ob->flag & SELECT))
+                                       init_render_object(re, ob, NULL, 0, 0);
+                       }
+               }
+       }
+       set_material_lightgroups(re);
+       
+       check_non_flat_quads(re);
+       /* don't call set_normalflags(), no flipping */
+       
+       if(type!=RE_BAKE_LIGHT) {
+               if(re->r.mode & R_SHADOW) {
+                       /* SHADOW BUFFER */
+                       for(go=re->lights.first; go; go= go->next) {
+                               LampRen *lar= go->lampren;
+                               
+                               if(re->test_break()) break;
+                               if(lar->shb) {
+                                       /* if type is irregular, this only sets the perspective matrix and autoclips */
+                                       /* but, that's not supported for bake... */
+                                       makeshadowbuf(re, lar);
+                               }
+                       }
+               }
+       }
+
+       if(type!=RE_BAKE_LIGHT) {
+               /* octree */
+               if(!re->test_break()) {
+                       if(re->r.mode & R_RAYTRACE) {
+                               makeoctree(re);
                        }
                }
        }
                        }
                }
        }
-       set_material_lightgroups(re);   
 }
 
 void RE_DataBase_GetView(Render *re, float mat[][4])
 }
 
 void RE_DataBase_GetView(Render *re, float mat[][4])
index cb2004e901de22f7fb9dd80c4eb2222535db7208..ca24f04a5803b96bebb0cece034162159a49129f 100644 (file)
@@ -667,6 +667,10 @@ static int intersection2(VlakRen *vlr, float r0, float r1, float r2, float rx1,
        float m0, m1, m2, divdet, det, det1;
        float u1, v, u2;
 
        float m0, m1, m2, divdet, det, det1;
        float u1, v, u2;
 
+       /* happens for baking with non existing face */
+       if(vlr->v1==NULL)
+               return 1;
+       
        v1= vlr->v1; 
        v2= vlr->v2; 
        if(vlr->v4) {
        v1= vlr->v1; 
        v2= vlr->v2; 
        if(vlr->v4) {
index ab74f4bfb849c8dc839dac58136d07ac9e5860aa..b6da7a3ecb794040aa9ed1a41f72efa160b3ab65 100644 (file)
 
 #include "BKE_global.h"
 #include "BKE_material.h"
 
 #include "BKE_global.h"
 #include "BKE_material.h"
+#include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_texture.h"
 
 #include "BKE_node.h"
 #include "BKE_texture.h"
 
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
 /* local include */
 #include "renderpipeline.h"
 #include "render_types.h"
 /* local include */
 #include "renderpipeline.h"
 #include "render_types.h"
@@ -1934,6 +1938,28 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
 
 }
 
 
 }
 
+static void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3)
+{
+       /* to prevent storing new tfaces or vcols, we check a split runtime */
+       /*              4---3           4---3 */
+       /*              |\ 1|   or  |1 /| */
+       /*              |0\ |           |/ 0| */
+       /*              1---2           1---2   0 = orig face, 1 = new face */
+       
+       /* Update vert nums to point to correct verts of original face */
+       if(vlr->flag & R_DIVIDE_24) {  
+               if(vlr->flag & R_FACE_SPLIT) {
+                       (*i1)++; (*i2)++; (*i3)++;
+               }
+               else {
+                       (*i3)++;
+               }
+       }
+       else if(vlr->flag & R_FACE_SPLIT) {
+               (*i2)++; (*i3)++; 
+       }
+}
+
 /* this function sets all coords for render (shared with raytracer) */
 /* warning; exception for ortho render is here, can be done better! */
 void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3)
 /* this function sets all coords for render (shared with raytracer) */
 /* warning; exception for ortho render is here, can be done better! */
 void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, int i3)
@@ -2202,24 +2228,8 @@ void shade_input_set_coords(ShadeInput *shi, float u, float v, int i1, int i2, i
                if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)))  {
                        int j1=i1, j2=i2, j3=i3;
                        
                if((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)))  {
                        int j1=i1, j2=i2, j3=i3;
                        
-                       /* to prevent storing new tfaces or vcols, we check a split runtime */
-                       /*              4---3           4---3 */
-                       /*              |\ 1|   or  |1 /| */
-                       /*              |0\ |           |/ 0| */
-                       /*              1---2           1---2   0 = orig face, 1 = new face */
-                       
-                       /* Update vert nums to point to correct verts of original face */
-                       if(vlr->flag & R_DIVIDE_24) {  
-                               if(vlr->flag & R_FACE_SPLIT) {
-                                       j1++; j2++; j3++;
-                               }
-                               else {
-                                       j3++;
-                               }
-                       }
-                       else if(vlr->flag & R_FACE_SPLIT) {
-                               j2++; j3++; 
-                       }
+                       /* uv and vcols are not copied on split, so set them according vlr divide flag */
+                       vlr_set_uv_indices(vlr, &j1, &j2, &j3);
                        
                        if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
                                
                        
                        if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
                                
@@ -3653,5 +3663,206 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr)
                shade_material_loop(shi, shr);
        }
 }
                shade_material_loop(shi, shr);
        }
 }
+/* ************************* bake ************************ */
+
+#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
+
+typedef struct BakeShade {
+       ShadeInput shi;
+       VlakRen *vlr;
+       
+       int rectx, recty, quad, type;
+       unsigned int *rect;
+       float *rect_float;
+} BakeShade;
 
 
+static void do_bake_shade(void *handle, int x, int y, float u, float v)
+{
+       BakeShade *bs= handle;
+       ShadeInput *shi= &bs->shi;
+       ShadeResult shr;
+       VlakRen *vlr= bs->vlr;
+       float l, *v1, *v2, *v3;
+       
+       shi->xs= x;
+       shi->ys= y;
+       
+       /* setup render coordinates, it's a copy of shade_ray mostly, but different.
+               like for shadepixel, useful to restructure once. */
+       if(bs->quad) {
+               v1= vlr->v1->co;
+               v2= vlr->v3->co;
+               v3= vlr->v4->co;
+       }
+       else {
+               v1= vlr->v1->co;
+               v2= vlr->v2->co;
+               v3= vlr->v3->co;
+       }
+       
+       /* renderco */
+       l= 1.0-u-v;
+       
+       shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
+       shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
+       shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
+       
+       /* set up view vector */
+       VECCOPY(shi->view, shi->co);
+       Normalise(shi->view);
+       
+       shi->vlr= vlr;
+       shi->mat= vlr->mat;
+       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));        // note, keep this synced with render_types.h
+       shi->har= shi->mat->har;
+       
+       /* no face normal flip */
+       VECCOPY(shi->facenor, vlr->n);
+       shi->puno= vlr->puno;
 
 
+       if(bs->quad) 
+               shade_input_set_coords(shi, -u, -v, 0, 3, 4);
+       else
+               shade_input_set_coords(shi, -u, -v, 0, 1, 2);
+       
+       if(bs->type==RE_BAKE_AO) {
+               shr.ao[0]= shr.ao[1]= shr.ao[2]= 0.0f;
+               ambient_occlusion(shi, &shr);
+               VECCOPY(shr.diff, shr.ao);
+       }
+       else {
+               if(shi->mat->nodetree && shi->mat->use_nodes) {
+                       ntreeShaderExecTree(shi->mat->nodetree, shi, &shr);
+                       shi->mat= vlr->mat;             /* shi->mat is being set in nodetree */
+               }
+               else
+                       shade_material_loop(shi, &shr);
+               
+               if(bs->type==RE_BAKE_NORMALS) {
+                       shr.diff[0]= shi->vn[0]/2.0f + 0.5f;
+                       shr.diff[1]= 0.5f - shi->vn[1]/2.0f;
+                       shr.diff[2]= shi->vn[2]/2.0f + 0.5f;
+               }               
+       }
+       
+       if(bs->rect) {
+               char *col= (char *)(bs->rect + bs->rectx*y + x);
+               col[0]= FTOCHAR(shr.diff[0]);
+               col[1]= FTOCHAR(shr.diff[1]);
+               col[2]= FTOCHAR(shr.diff[2]);
+               col[3]= 255;
+       }
+       else {
+               float *col= bs->rect_float + 4*(bs->rectx*y + x);
+               VECCOPY(col, shr.diff);
+               col[3]= 1.0f;
+       }
+}
+
+/* already have tested for tface and ima */
+static void shade_tface(BakeShade *bs, VlakRen *vlr)
+{
+       TFace *tface= vlr->tface;
+       Image *ima= tface->tpage;
+       ZSpan *zspan= (ZSpan *)ima->id.newid;
+       float vec[4][2];
+       int a, i1, i2, i3;
+       
+       if(ima->ibuf==NULL)
+               return;
+       
+       /* signal we find this image for the first time */
+       if(zspan==NULL) {
+               if(ima->ibuf->rect==NULL && ima->ibuf->rect_float==NULL)
+                       return;
+               /* we either fill in float or char, this ensures things go fine */
+               if(ima->ibuf->rect_float)
+                       imb_freerectImBuf(ima->ibuf);
+               
+               zspan= MEM_mallocN(sizeof(ZSpan), "zspan for bake");
+               zbuf_alloc_span(zspan, ima->ibuf->x, ima->ibuf->y);
+               ima->id.newid= (ID *)zspan;
+               
+               memset(vec, 0, sizeof(vec));
+               IMB_rectfill(ima->ibuf, vec[0]);
+       }
+       
+       bs->vlr= vlr;
+       bs->rectx= ima->ibuf->x;
+       bs->recty= ima->ibuf->y;
+       bs->rect= ima->ibuf->rect;
+       bs->rect_float= ima->ibuf->rect_float;
+       bs->quad= 0;
+       
+       /* get pixel level vertex coordinates */
+       for(a=0; a<4; a++) {
+               vec[a][0]= tface->uv[a][0]*(float)bs->rectx - 0.5f;
+               vec[a][1]= tface->uv[a][1]*(float)bs->recty - 0.5f;
+       }
+       
+       /* UV indices have to be corrected for possible quad->tria splits */
+       i1= 0; i2= 1; i3= 2;
+       vlr_set_uv_indices(vlr, &i1, &i2, &i3);
+       zspan_scanconvert(zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade);
+       
+       if(vlr->v4) {
+               bs->quad= 1;
+               zspan_scanconvert(zspan, bs, vec[0], vec[2], vec[3], do_bake_shade);
+       }
+}
+
+/* using object selection tags, the faces with UV maps get baked */
+/* render should have been setup */
+void RE_bake_shade_all_selected(Render *re, int type)
+{
+       BakeShade handle;
+       Image *ima;
+       VlakRen *vlr= NULL;
+       int v, vdone=0;
+       
+       /* initialize render global */
+       R= *re;
+       
+       /* set defaults in handle */
+       memset(&handle, 0, sizeof(BakeShade));
+       handle.shi.lay= re->scene->lay;
+       handle.type= type;
+       
+       /* baker abuses newid for zspans */
+       for(ima= G.main->image.first; ima; ima= ima->id.next)
+               ima->id.newid= NULL;
+       
+       for(v=0; v<R.totvlak; v++) {
+               if((v & 255)==0)
+                       vlr= R.blovl[v>>8];
+               else vlr++;
+               
+               if(vlr->ob->flag & SELECT) {
+                       if(vlr->tface && vlr->tface->tpage) {
+                               shade_tface(&handle, vlr);
+                               vdone++;
+                               
+                               if((vdone & 1023)==1)
+                                       R.timecursor(vdone>>10);
+                               
+                               if(R.test_break()) break; 
+                       }
+               }
+       }
+       
+       /* free zspans, filter images */
+       for(ima= G.main->image.first; ima; ima= ima->id.next) {
+               if(ima->id.newid) {
+                       extern void free_realtime_image(Image *ima);    /* bad level call */
+                       
+                       zbuf_free_span((ZSpan *)ima->id.newid);
+                       MEM_freeN(ima->id.newid);
+                       ima->id.newid= NULL;
+                       
+                       IMB_filter_extend(ima->ibuf);
+                       ima->ibuf->userflags |= IB_BITMAPDIRTY;
+                       free_realtime_image(ima); /* force OpenGL reload */
+               }
+       }
+       
+}
index 1b8a658e8272e6e9145e3e5c8751cbaa8530c6e0..737f4884dddbfefb2eb36380e335dce2be1bbc13 100644 (file)
@@ -1308,6 +1308,96 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int zvlnr, float *v1, float *v2, floa
        }
 }
 
        }
 }
 
+/* 2d scanconvert for tria, calls func for each x,y coordinate and gives UV barycentrics */
+/* zspan should be initialized, has rect size and span buffers */
+
+void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float) )
+{
+       float x0, y0, x1, y1, x2, y2, z0, z1, z2;
+       float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
+       float *span1, *span2;
+       int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
+       
+       /* init */
+       zbuf_init_span(zspan);
+       
+       /* set spans */
+       zbuf_add_to_span(zspan, v1, v2);
+       zbuf_add_to_span(zspan, v2, v3);
+       zbuf_add_to_span(zspan, v3, v1);
+       
+       /* clipped */
+       if(zspan->minp2==NULL || zspan->maxp2==NULL) return;
+       
+       if(zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
+       if(zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+       
+       //      printf("my %d %d\n", my0, my2);
+       if(my2<my0) return;
+       
+       /* ZBUF DX DY, in floats still */
+       x1= v1[0]- v2[0];
+       x2= v2[0]- v3[0];
+       y1= v1[1]- v2[1];
+       y2= v2[1]- v3[1];
+       
+       z1= 1.0f; // (u1 - u2)
+       z2= 0.0f; // (u2 - u3)
+       
+       x0= y1*z2-z1*y2;
+       y0= z1*x2-x1*z2;
+       z0= x1*y2-y1*x2;
+       
+       if(z0==0.0f) return;
+       
+       xx1= (x0*v1[0] + y0*v1[1])/z0 + 1.0f;   
+       uxd= -(double)x0/(double)z0;
+       uyd= -(double)y0/(double)z0;
+       uy0= ((double)my2)*uyd + (double)xx1;
+
+       z1= -1.0f; // (v1 - v2)
+       z2= 1.0f;  // (v2 - v3)
+       
+       x0= y1*z2-z1*y2;
+       y0= z1*x2-x1*z2;
+       
+       xx1= (x0*v1[0] + y0*v1[1])/z0;
+       vxd= -(double)x0/(double)z0;
+       vyd= -(double)y0/(double)z0;
+       vy0= ((double)my2)*vyd + (double)xx1;
+       
+       /* correct span */
+       sn1= (my0 + my2)/2;
+       if(zspan->span1[sn1] < zspan->span2[sn1]) {
+               span1= zspan->span1+my2;
+               span2= zspan->span2+my2;
+       }
+       else {
+               span1= zspan->span2+my2;
+               span2= zspan->span1+my2;
+       }
+       
+       for(y=my2; y>=my0; y--, span1--, span2--) {
+               
+               sn1= floor(*span1);
+               sn2= floor(*span2);
+               sn1++; 
+               
+               if(sn2>=rectx) sn2= rectx-1;
+               if(sn1<0) sn1= 0;
+               
+               u= (double)sn1*uxd + uy0;
+               v= (double)sn1*vxd + vy0;
+               
+               for(x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
+                       func(handle, x, y, u, v);
+               
+               uy0 -= uyd;
+               vy0 -= vyd;
+       }
+}
+
+
 
 /**
  * (clip pyramid)
 
 /**
  * (clip pyramid)
index d062423e7e1529f5c2dd20a2363d3111d94e26b9..57b35174acdedbba0133643434e9012e6b568149 100644 (file)
@@ -68,6 +68,7 @@
 #include "BIF_interface.h"
 #include "BIF_language.h"
 #include "BIF_mainqueue.h"
 #include "BIF_interface.h"
 #include "BIF_language.h"
 #include "BIF_mainqueue.h"
+#include "BIF_meshtools.h"
 #include "BIF_previewrender.h"
 #include "BIF_renderwin.h"
 #include "BIF_resources.h"
 #include "BIF_previewrender.h"
 #include "BIF_renderwin.h"
 #include "BIF_resources.h"
@@ -1672,6 +1673,9 @@ static void do_info_rendermenu(void *arg, int event)
        case 7:
                extern_set_butspace(F10KEY, 0);
                break;
        case 7:
                extern_set_butspace(F10KEY, 0);
                break;
+       case 8:
+               objects_bake_render();
+               break;
        }
        allqueue(REDRAWINFO, 0);
 }
        }
        allqueue(REDRAWINFO, 0);
 }
@@ -1688,6 +1692,7 @@ static uiBlock *info_rendermenu(void *arg_unused)
        
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Render Current Frame|F12",       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Render Animation|Ctrl F12",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
        
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Render Current Frame|F12",       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Render Animation|Ctrl F12",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Bake-Render Meshes|ALT+Ctrl B",          0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
 
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
 
        uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
index 677ae69d4adb801abefd45e9dfb50b2f7b1bb5c7..2182e5ccc37cd59c0353efda609e872853d629aa 100644 (file)
@@ -60,6 +60,7 @@ void sort_faces(void);
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
@@ -75,6 +76,7 @@ void sort_faces(void);
 
 #include "BIF_editmesh.h"
 #include "BIF_graphics.h"
 
 #include "BIF_editmesh.h"
 #include "BIF_graphics.h"
+#include "BIF_interface.h"
 #include "BIF_mywindow.h"
 #include "BIF_screen.h"
 #include "BIF_space.h"
 #include "BIF_mywindow.h"
 #include "BIF_screen.h"
 #include "BIF_space.h"
@@ -91,6 +93,9 @@ void sort_faces(void);
 
 #include "BIF_meshtools.h" /* include ourself for prototypes */
 
 
 #include "BIF_meshtools.h" /* include ourself for prototypes */
 
+#include "RE_pipeline.h"
+#include "RE_shader_ext.h"
+
 
 /* * ********************** no editmode!!! *********** */
 
 
 /* * ********************** no editmode!!! *********** */
 
@@ -852,3 +857,45 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co)
        return NULL;
 }
 
        return NULL;
 }
 
+
+/* ****************** render BAKING ********************** */
+
+/* all selected meshes with UV maps are rendered for current scene visibility */
+void objects_bake_render(void)
+{
+       short event;
+       
+       event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3");
+       if(event>0) {
+               Render *re= RE_NewRender("_Bake View_");
+               
+               if(event==1) event= RE_BAKE_ALL;
+               else if(event==2) event= RE_BAKE_AO;
+               else event= RE_BAKE_NORMALS;
+               
+               if(event==RE_BAKE_AO) {
+                       if((G.scene->r.mode & R_RAYTRACE)==0 || G.scene->world==NULL
+                          || (G.scene->world->mode & WO_AMB_OCC)==0) {
+                               error("No AO set up");
+                               return;
+                       }
+               }
+               
+               waitcursor(1);
+               RE_timecursor_cb(re, set_timecursor);
+               RE_test_break_cb(re, blender_test_break);
+               G.afbreek= 0;   /* blender_test_break uses this global */
+               
+               RE_Database_Baking(re, G.scene, event);
+               
+               RE_bake_shade_all_selected(re, event);
+               
+               RE_Database_Free(re);
+               waitcursor(0);
+               
+               allqueue(REDRAWIMAGE, 0);
+               allqueue(REDRAWVIEW3D, 0);
+       }
+}
+
+
index 48ffb96018909c8fe18fb83b8dd6456c8f06391c..078c6f6a8864d67f0ed338607cf05a99e04c6f0b 100644 (file)
@@ -1328,6 +1328,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                fluidsimBake(NULL);
                                        }
                                }
                                                fluidsimBake(NULL);
                                        }
                                }
+                               else if(G.qual== (LR_ALTKEY|LR_CTRLKEY))
+                                       objects_bake_render();
                                else if(G.qual==0)
                                        borderselect();
                                break;
                                else if(G.qual==0)
                                        borderselect();
                                break;