From 0e935e397b945d2a8d76eb1c748e8bc11bca0095 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 22 Feb 2008 14:27:46 +0000 Subject: [PATCH] * Displacement baking wasnt working with negative distances. * Added Normalize option for diplacement so everything in the 'Dist' range is mapped 0-1 * Increased the maximum Dist and Bias to1000.0 (was 10.0) * Added python utility function in BPyRender.py - bakeToPlane(...), to automate heightmap, normalmap generation for Crystalspace. --- release/scripts/bpymodules/BPyRender.py | 132 ++++++++++++++++++ source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/python/api2_2x/sceneRender.c | 6 +- .../blender/render/intern/source/rendercore.c | 10 +- source/blender/src/buttons_scene.c | 14 +- 5 files changed, 152 insertions(+), 12 deletions(-) diff --git a/release/scripts/bpymodules/BPyRender.py b/release/scripts/bpymodules/BPyRender.py index e335ee7f6a8..7b1ccc7a0bd 100644 --- a/release/scripts/bpymodules/BPyRender.py +++ b/release/scripts/bpymodules/BPyRender.py @@ -496,3 +496,135 @@ def vcol2image(me_s,\ mat.mode &= ~Blender.Material.Modes.SHADELESS return image + +def bakeToPlane(sce, ob_from, width, height, bakemodes, axis='z', margin=0): + ''' + Bakes terrain onto a plane from one object + sce - scene to bake with + ob_from - mesh object + width/height - image size + bakemodes - list of baking modes to use, Blender.Scene.Render.BakeModes.NORMALS, Blender.Scene.Render.BakeModes.AO ... etc + axis - axis to allign the plane to. + margin - margin setting for baking. + + Example: + import Blender + from Blender import * + import BPyRender + sce = Scene.GetCurrent() + ob = Object.Get('Plane') + BPyRender.bakeToPlane(sce, ob, 512, 512, [Scene.Render.BakeModes.DISPLACEMENT, Scene.Render.BakeModes.NORMALS], 'z', 8 ) + ''' + + # Backup bake settings + rend = sce.render + BACKUP_bakeDist = rend.bakeDist + BACKUP_bakeBias = rend.bakeBias + BACKUP_bakeMode = rend.bakeMode + BACKUP_bakeClear = rend.bakeClear + BACKUP_bakeMargin = rend.bakeMargin + BACKUP_bakeToActive = rend.bakeToActive + + # Backup object selection + BACKUP_obsel = list(sce.objects.selected) + BACKUP_obact = sce.objects.active + + # New bake settings + rend.bakeClear = True + rend.bakeMargin = margin + BACKUP_bakeToActive = True + + # Assume a mesh + me_from = ob_from.getData(mesh=1) + + xmin = ymin = zmin = 10000000000 + xmax = ymax = zmax =-10000000000 + + # Dont trust bounding boxes :/ + #bounds = ob_from.boundingBox + #for v in bounds: + # x,y,z = tuple(v) + mtx = ob_from.matrixWorld + for v in me_from.verts: + x,y,z = tuple(v.co*mtx) + + xmax = max(xmax, x) + ymax = max(ymax, y) + zmax = max(zmax, z) + + xmin = min(xmin, x) + ymin = min(ymin, y) + zmin = min(zmin, z) + + if axis=='x': + xmed = (xmin+xmax)/2.0 + co1 = (xmed, ymin, zmin) + co2 = (xmed, ymin, zmax) + co3 = (xmed, ymax, zmax) + co4 = (xmed, ymax, zmin) + rend.bakeDist = (xmax-xmin)/2.0 + elif axis=='y': + ymed = (ymin+ymax)/2.0 + co1 = (xmin, ymed, zmin) + co2 = (xmin, ymed, zmax) + co3 = (xmax, ymed, zmax) + co4 = (xmax, ymed, zmin) + rend.bakeDist = (ymax-ymin)/2.0 + elif axis=='z': + zmed = (zmin+zmax)/2.0 + co1 = (xmin, ymin, zmed) + co2 = (xmin, ymax, zmed) + co3 = (xmax, ymax, zmed) + co4 = (xmax, ymin, zmed) + rend.bakeDist = (zmax-zmin)/2.0 + else: + raise "invalid axis" + me_plane = Blender.Mesh.New() + ob_plane = Blender.Object.New('Mesh') + ob_plane.link(me_plane) + sce.objects.link(ob_plane) + ob_plane.Layers = ob_from.Layers + + ob_from.sel = 1 # make active + sce.objects.active = ob_plane + ob_plane.sel = 1 + + me_plane.verts.extend([co4, co3, co2, co1]) + me_plane.faces.extend([(0,1,2,3)]) + me_plane.faceUV = True + me_plane_face = me_plane.faces[0] + uvs = me_plane_face.uv + uvs[0].x = 0.0; uvs[0].y = 0.0 + uvs[1].x = 0.0; uvs[1].y = 1.0 + uvs[2].x = 1.0; uvs[2].y = 1.0 + uvs[3].x = 1.0; uvs[3].y = 0.0 + + images_return = [] + + for mode in bakemodes: + img = Blender.Image.New('bake', width, height, 24) + + me_plane_face.image = img + rend.bakeMode = mode + rend.bake() + images_return.append( img ) + + # Restore bake settings + #''' + rend.bakeDist = BACKUP_bakeDist + rend.bakeBias = BACKUP_bakeBias + rend.bakeMode = BACKUP_bakeMode + rend.bakeClear = BACKUP_bakeClear + rend.bakeMargin = BACKUP_bakeMargin + rend.bakeToActive = BACKUP_bakeToActive + + # Restore obsel + sce.objects.selected = BACKUP_obsel + sce.objects.active = BACKUP_obact + + me_plane.verts = None + sce.objects.unlink(ob_plane) + #''' + + return me_plane_face + diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 9b24d8214b0..d42c3a48713 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -676,7 +676,7 @@ typedef struct Scene { #define R_BAKE_CLEAR 1 #define R_BAKE_OSA 2 #define R_BAKE_TO_ACTIVE 4 -#define R_BAKE_NORMALIZE_AO 8 +#define R_BAKE_NORMALIZE 8 /* bake_normal_space */ #define R_BAKE_SPACE_CAMERA 0 diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 62ddd5a33bb..4bf823bc938 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -1899,12 +1899,12 @@ static int RenderData_setFloatAttrClamp( BPy_RenderData *self, PyObject *value, break; case EXPP_RENDER_ATTR_BAKEDIST: min = 0.0f; - max = 10.0f; + max = 1000.0f; param = &self->renderContext->bake_maxdist; break; case EXPP_RENDER_ATTR_BAKEBIAS: min = 0.0f; - max = 10.0f; + max = 1000.0f; param = &self->renderContext->bake_biasdist; break; default: @@ -2880,7 +2880,7 @@ static PyGetSetDef BPy_RenderData_getseters[] = { {"bakeNormalizeAO", (getter)RenderData_getBakeMode, (setter)RenderData_setBakeMode, "Bake selection to active", - (void *)R_BAKE_NORMALIZE_AO}, + (void *)R_BAKE_NORMALIZE}, {"bakeMargin", (getter)RenderData_getIValueAttr, (setter)RenderData_setIValueAttrClamp, "number of pixels to use as a margin for the edges of the image", diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 84536d38490..c72edabc65c 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1855,7 +1855,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int if(bs->type==RE_BAKE_AO) { ambient_occlusion(shi); - if(R.r.bake_flag & R_BAKE_NORMALIZE_AO) + if(R.r.bake_flag & R_BAKE_NORMALIZE) VECCOPY(shr.combined, shi->ao) else ambient_occlusion_to_diffuse(shi, shr.combined); @@ -1934,7 +1934,11 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x, BakeShade *bs= handle; float disp; - disp = 0.5 + dist; + if(R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) { + disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ + } else { + disp = 0.5 + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ + } if(bs->rect_float) { float *col= bs->rect_float + 4*(bs->rectx*y + x); @@ -2066,7 +2070,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) } if (hit && bs->type==RE_BAKE_DISPLACEMENT) {; - bake_displacement(handle, shi, mindist, x, y); + bake_displacement(handle, shi, (dir==-1)? -mindist:mindist, x, y); return; } diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 9fcd093acb2..14a660376ae 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -2085,16 +2085,20 @@ static void render_panel_bake(void) uiBlockBeginAlign(block); uiDefButBitS(block, TOG, R_BAKE_TO_ACTIVE, B_DIFF, "Selected to Active", 10,120,190,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Bake shading on the surface of selected objects to the active object"); - uiDefButF(block, NUM, B_DIFF, "Dist:", 10,100,95,20,&G.scene->r.bake_maxdist, 0.0, 10.0, 1, 0, "Maximum distance from active object to other object (in blender units)"); - uiDefButF(block, NUM, B_DIFF, "Bias:", 105,100,95,20,&G.scene->r.bake_biasdist, 0.0, 10.0, 1, 0, "Bias towards faces further away from the object (in blender units)"); + uiDefButF(block, NUM, B_DIFF, "Dist:", 10,100,95,20,&G.scene->r.bake_maxdist, 0.0, 1000.0, 1, 0, "Maximum distance from active object to other object (in blender units)"); + uiDefButF(block, NUM, B_DIFF, "Bias:", 105,100,95,20,&G.scene->r.bake_biasdist, 0.0, 1000.0, 1, 0, "Bias towards faces further away from the object (in blender units)"); uiBlockEndAlign(block); if(G.scene->r.bake_mode == RE_BAKE_NORMALS) uiDefButS(block, MENU, B_DIFF, "Normal Space %t|Camera %x0|World %x1|Object %x2|Tangent %x3", 10,70,190,20, &G.scene->r.bake_normal_space, 0, 0, 0, 0, "Choose normal space for baking"); - else if(G.scene->r.bake_mode == RE_BAKE_AO) - uiDefButBitS(block, TOG, R_BAKE_NORMALIZE_AO, B_DIFF, "Normalized", 10,70,190,20, &G.scene->r.bake_flag, 0.0, 0, 0, 0, "Bake ambient occlusion normalized, without taking into acount material settings"); - + else if(G.scene->r.bake_mode == RE_BAKE_AO || G.scene->r.bake_mode == RE_BAKE_DISPLACEMENT) { + uiDefButBitS(block, TOG, R_BAKE_NORMALIZE, B_DIFF, "Normalized", 10,70,190,20, &G.scene->r.bake_flag, 0.0, 0, 0, 0, + G.scene->r.bake_mode == RE_BAKE_AO ? + "Bake ambient occlusion normalized, without taking into acount material settings": + "Normalized displacement value to fit the 'Dist' range" + ); + } #if 0 uiBlockBeginAlign(block); uiDefButBitS(block, TOG, R_BAKE_OSA, B_DIFF, "OSA", 10,120,190,20, &G.scene->r.bake_flag, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)");