forked from bartvdbraak/blender
* 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:
parent
d7088ce825
commit
0e935e397b
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)");
|
||||
|
Loading…
Reference in New Issue
Block a user