class Book: def __init__(self, cover_height, cover_thickness, cover_depth, page_height, page_depth, page_thickness, spine_curl, hinge_inset, hinge_width, book_width, lean, lean_angle, subsurf, material): self.height = cover_height self.width = page_thickness + 2 * cover_thickness self.depth = cover_depth self.lean_angle = lean_angle self.lean = lean self.page_thickness = page_thickness self.page_height = page_height self.page_depth = page_depth self.cover_depth = cover_depth self.cover_height = cover_height self.cover_thickness = cover_thickness self.hinge_inset = hinge_inset self.hinge_width = hinge_width self.spine_curl = spine_curl self.subsurf = subsurf self.material = material self.location = Vector([0, 0, 0]) self.rotation = Vector([0, 0, 0]) self.verts = get_verts(page_thickness, page_height, cover_depth, cover_height, cover_thickness, page_depth, hinge_inset, hinge_width, spine_curl) self.faces = get_faces() def to_object(self): def index_to_vert(face): lst = [] for i in face: lst.append(vert_ob[i]) return tuple(lst) mesh = bpy.data.meshes.new("book") self.creases = get_creases() self.uvs = get_uvs(self.page_thickness, self.page_height, self.cover_depth, self.cover_height, self.cover_thickness, self.page_depth, self.hinge_inset, self.hinge_width, self.spine_curl) self.obj = bpy.data.objects.new("book", mesh) bm = bmesh.new() bm.from_mesh(mesh) vert_ob = [] for vert in self.verts: vert_ob.append(bm.verts.new(vert)) bm.verts.index_update() bm.verts.ensure_lookup_table() cl = bm.edges.layers.crease.verify() for c in self.creases: e = bm.edges.new((bm.verts[c[0]], bm.verts[c[1]])) e[cl] = 1.0 for face in self.faces: f = bm.faces.new(index_to_vert(face)) f.smooth = True bm.faces.index_update() bm.edges.ensure_lookup_table() uv_layer = bm.loops.layers.uv.verify() for (f, uvs) in zip(bm.faces, self.uvs): for (l, uv) in zip(f.loops, uvs): loop_uv = l[uv_layer] loop_uv.uv.x = uv[0] loop_uv.uv.y = uv[1] bm.normal_update() bm.to_mesh(mesh) bm.free() # calculate auto smooth angle based on spine center = self.verts[-1] side = self.verts[-5] curl = abs(center[1] - side[1]) width = abs(center[0] - side[0]) spine_angle = atan(width / curl) * 2 normal_angle = radians(180) - spine_angle + radians( 1) # add 1 deg to account for fp mesh.use_auto_smooth = True mesh.auto_smooth_angle = normal_angle if (self.subsurf): self.obj.modifiers.new("subd", type='SUBSURF') self.obj.modifiers['subd'].levels = 1 if (self.material): if self.obj.data.materials: self.obj.data.materials[0] = self.material else: self.obj.data.materials.append(self.material) self.obj.matrix_world = Matrix.Translation( self.location) @ self.rotation.to_4x4() return self.obj def get_geometry(self): transformed_verts = map( lambda v: self.rotation @ Vector(v) + self.location, self.verts) return transformed_verts, self.faces
class Book: """ This stores information about a single book. It can export the book as blender object or return the raw geometry for previz. """ def __init__( self, cover_height, cover_thickness, cover_depth, page_height, page_depth, page_thickness, spine_curl, hinge_inset, hinge_width, lean=0, lean_angle=0, subsurf=False, cover_material=None, page_material=None ): self.height = cover_height self.width = page_thickness + 2 * cover_thickness self.depth = cover_depth self.lean_angle = lean_angle self.lean = lean self.page_thickness = page_thickness self.page_height = page_height self.page_depth = page_depth self.cover_depth = cover_depth self.cover_height = cover_height self.cover_thickness = cover_thickness self.hinge_inset = hinge_inset self.hinge_width = hinge_width self.spine_curl = spine_curl self.subsurf = subsurf self.cover_material = cover_material self.page_material = page_material self.location = Vector([0, 0, 0]) self.rotation = Vector([0, 0, 0]) self.obj = None self.vertices = get_vertices( page_thickness, page_height, cover_depth, cover_height, cover_thickness, page_depth, hinge_inset, hinge_width, spine_curl) self.faces = get_faces() def to_object(self, with_uvs=False): """ Exports the book as a blender object """ def index_to_vert(face): lst = [] for i in face: lst.append(vert_ob[i]) return tuple(lst) mesh = bpy.data.meshes.new("book") creases = get_creases() if with_uvs: uvs = get_uvs( self.page_thickness, self.page_height, self.cover_depth, self.cover_height, self.cover_thickness, self.page_depth, self.hinge_inset, self.hinge_width, self.spine_curl) self.obj = bpy.data.objects.new("book", mesh) bm = bmesh.new() bm.from_mesh(mesh) vert_ob = [] for vert in self.vertices: vert_ob.append(bm.verts.new(vert)) bm.verts.index_update() bm.verts.ensure_lookup_table() crease_layer = bm.edges.layers.crease.verify() for crease in creases: edge = bm.edges.new((bm.verts[crease[0]], bm.verts[crease[1]])) edge[crease_layer] = 1.0 for face_index in self.faces: face = bm.faces.new(index_to_vert(face_index)) face.smooth = True bm.faces.index_update() bm.edges.ensure_lookup_table() if with_uvs: uv_layer = bm.loops.layers.uv.verify() for (face, face_uvs) in zip(bm.faces, uvs): for (loop, uv) in zip(face.loops, face_uvs): loop_uv = loop[uv_layer] loop_uv.uv.x = uv[0] loop_uv.uv.y = uv[1] bm.normal_update() # calculate auto smooth angle based on spine center = self.vertices[-1] side = self.vertices[-5] curl = abs(center[1] - side[1]) width = abs(center[0] - side[0]) spine_angle = atan(width / curl) * 2 normal_angle = radians(180) - spine_angle + radians(1) # add 1 deg to account for fp mesh.use_auto_smooth = True mesh.auto_smooth_angle = normal_angle if self.subsurf: self.obj.modifiers.new("Subdivision Surface", type='SUBSURF') self.obj.modifiers['Subdivision Surface'].levels = 1 if self.cover_material: if self.obj.data.materials: self.obj.data.materials[0] = self.cover_material else: self.obj.data.materials.append(self.cover_material) if self.page_material: self.obj.data.materials.append(self.page_material) bm.faces.ensure_lookup_table() bm.faces[0].material_index = 1 bm.faces[1].material_index = 1 bm.faces[2].material_index = 1 bm.faces[3].material_index = 1 self.obj.matrix_world = Matrix.Translation(self.location) @ self.rotation.to_4x4() bm.to_mesh(mesh) bm.free() return self.obj def get_geometry(self): """ Returns the raw geometry of a book """ transformed_verts = map(lambda v: self.rotation @ Vector(v) + self.location, self.vertices) return transformed_verts, self.faces