From c47fa4d0ecefea3f32448cb89610a4cc28aac2bb Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 19 Nov 2006 14:12:56 +0000 Subject: Long waited feature: Render Baking 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 --- .../blenkernel/bad_level_call_stubs/stubs.c | 2 +- source/blender/blenkernel/intern/displist.c | 30 ++- source/blender/imbuf/IMB_imbuf.h | 1 + source/blender/imbuf/intern/filter.c | 111 +++++++-- source/blender/include/BIF_meshtools.h | 1 + source/blender/render/extern/include/RE_pipeline.h | 9 +- .../blender/render/extern/include/RE_shader_ext.h | 4 +- source/blender/render/intern/include/zbuf.h | 3 + .../blender/render/intern/source/convertblender.c | 79 ++++++- source/blender/render/intern/source/ray.c | 4 + source/blender/render/intern/source/rendercore.c | 247 +++++++++++++++++++-- source/blender/render/intern/source/zbuf.c | 90 ++++++++ source/blender/src/header_info.c | 5 + source/blender/src/meshtools.c | 47 ++++ source/blender/src/space.c | 2 + 15 files changed, 571 insertions(+), 64 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 18b59a75133..824c1566100 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -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_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) {} diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 4ac3ea2aac2..5e3439da6bf 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -377,7 +377,7 @@ static Render *fastshade_get_render(void) 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; } @@ -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; @@ -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); + VECCOPY(shi.facenor, shi.vn); 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.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); @@ -567,11 +574,12 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un for (i=0; itotface; 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; - Material *ma= give_current_material(ob, mf->mat_nr+1); 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; - + float *uv= tface?tface->uv[j]:NULL; + 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); @@ -705,7 +717,7 @@ void shadeDispList(Base *base) 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++; } @@ -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); - fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL); 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); - fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + fastshade(vec, n1, fp, NULL, ma, (char *)col1, NULL, NULL); fp+= 3; col1++; nor+= 3; } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 79d2d148c19..02b3557c094 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -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_extend(struct ImBuf *ibuf); /** * diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 8c5bc430aea..343211eb6b0 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -132,27 +132,27 @@ void IMB_filtery(struct ImBuf *ibuf) { 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; - if (ibuf->rect_float != NULL) do_float = 1; - 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); @@ -170,27 +170,27 @@ void imb_filterx(struct ImBuf *ibuf) { 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; - if (ibuf->rect_float != NULL) do_float = 1; - 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); @@ -239,3 +239,66 @@ void IMB_filter(struct ImBuf *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; xscene= 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 */ @@ -3920,9 +3941,18 @@ void RE_Database_Shaded(Render *re, Scene *scene) 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); - + 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); - 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]) diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c index cb2004e901d..ca24f04a580 100644 --- a/source/blender/render/intern/source/ray.c +++ b/source/blender/render/intern/source/ray.c @@ -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; + /* happens for baking with non existing face */ + if(vlr->v1==NULL) + return 1; + v1= vlr->v1; v2= vlr->v2; if(vlr->v4) { diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index ab74f4bfb84..b6da7a3ecb7 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -56,9 +56,13 @@ #include "BKE_global.h" #include "BKE_material.h" +#include "BKE_main.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" @@ -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) @@ -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; - /* 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)) { @@ -3653,5 +3663,206 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *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>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 */ + } + } + +} diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 1b8a658e827..737f4884ddd 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -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(my2span1[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) diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index d062423e7e1..57b35174acd 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -68,6 +68,7 @@ #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" @@ -1672,6 +1673,9 @@ static void do_info_rendermenu(void *arg, int event) case 7: extern_set_butspace(F10KEY, 0); break; + case 8: + objects_bake_render(); + break; } 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, "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, ""); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 677ae69d4ad..2182e5ccc37 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -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_world_types.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_interface.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 "RE_pipeline.h" +#include "RE_shader_ext.h" + /* * ********************** no editmode!!! *********** */ @@ -852,3 +857,45 @@ EditVert *editmesh_get_x_mirror_vert(Object *ob, float *co) 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); + } +} + + diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 48ffb960189..078c6f6a886 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1328,6 +1328,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) fluidsimBake(NULL); } } + else if(G.qual== (LR_ALTKEY|LR_CTRLKEY)) + objects_bake_render(); else if(G.qual==0) borderselect(); break; -- cgit v1.2.3