* 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.
This commit is contained in:
Campbell Barton 2008-02-22 14:27:46 +00:00
parent d7088ce825
commit 0e935e397b
5 changed files with 152 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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;
}

View File

@ -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)");