blender as research tool · sybren a. stüvel - [email protected] blender as research tool: from...

50
Blender as research tool Blender as research tool from data to visualization from data to visualization

Upload: others

Post on 06-Jul-2020

15 views

Category:

Documents


0 download

TRANSCRIPT

Blender as research toolBlender as research toolfrom data to visualizationfrom data to visualization

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Sybren A. StüvelSybren A. Stüvel

● Blender user for 10 yearsBlender user for 10 years● Python user for 8 yearsPython user for 8 years● Programming & drumming since 1991Programming & drumming since 1991● Doing a PhD in crowd animation (Universiteit Utrecht)Doing a PhD in crowd animation (Universiteit Utrecht)

● http://stuvel.eu/http://stuvel.eu/http://stuvelfoto.nl/http://stuvelfoto.nl/http://soundabout.nl/http://soundabout.nl/

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Overview of the workshopOverview of the workshop

● My researchMy research● Creating 3D objects with PythonCreating 3D objects with Python● Easier reuse: creating an OperatorEasier reuse: creating an Operator● Extending the user interfaceExtending the user interface● Loading from a databaseLoading from a database● Putting it all togetherPutting it all together● DiscussionDiscussion

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

My researchMy research

● Utrecht UniversityUtrecht University● Virtual Human Technology LabVirtual Human Technology Lab

● Crowd animationCrowd animation● Densely packedDensely packed

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Bounding Circle HierarchyBounding Circle Hierarchy

● Occupancy spacesOccupancy spaces● Represented using Represented using

Bounding Circle HierarchiesBounding Circle Hierarchies● Find bounding circleFind bounding circle● Recursively subdivideRecursively subdivide

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Bounding Circle HierarchyBounding Circle Hierarchy

● Occupancy spacesOccupancy spaces● Represented using Represented using

Bounding Circle HierarchiesBounding Circle Hierarchies● Find bounding circleFind bounding circle● Recursively subdivideRecursively subdivide

● Stop when they are small Stop when they are small enoughenough

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Bounding Circle HierarchyBounding Circle Hierarchy

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Intersection testsIntersection tests

● Intersections between BCHsIntersections between BCHs● Bottom circles don't Bottom circles don't

intersect no intersection→intersect no intersection→● Otherwise: check sub-circlesOtherwise: check sub-circles● Tricky, and of course I made Tricky, and of course I made

a mistake...a mistake...

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Benchmarking the audienceBenchmarking the audience

● Who has experience with...Who has experience with...● … … programming?programming?● … … programming in Python?programming in Python?● … … Blender scripting with Python?Blender scripting with Python?● … … Linear algebra / coordinate transformations?Linear algebra / coordinate transformations?

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Please interruptPlease interrupt

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

CodingCoding

1)Create a circle mesh from PythonCreate a circle mesh from Python

2)Duplicate it a lotDuplicate it a lot

3)Create an OperatorCreate an Operator

4)Connect it to the GUIConnect it to the GUI

5)Connect to the databaseConnect to the database

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objects

We need to:We need to:

● Add a circleAdd a circle● Scale itScale it● Position itPosition it

… … and do it again, and again, and again....and do it again, and again, and again....

As one hierarchy contains roughly 1400 circles!As one hierarchy contains roughly 1400 circles!

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objects

● Ensure there is one circle meshEnsure there is one circle mesh– ±± 1500 circles per hierarchy 1500 circles per hierarchy

– 32 vertices per circle32 vertices per circle

– 2 hierarchies2 hierarchies

– 96000 vertices96000 vertices

● For each circle, create object that shares this meshFor each circle, create object that shares this mesh

● Scale & position the objectScale & position the object

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objects

● Ensure there is one circle meshEnsure there is one circle mesh– ±± 1500 circles per hierarchy 1500 circles per hierarchy

– 32 vertices per circle32 vertices per circle

– 2 hierarchies2 hierarchies

– 96000 vertices96000 vertices

● For each circle, create object that shares this meshFor each circle, create object that shares this mesh

● Scale & position the objectScale & position the object

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objects

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

If you don't see the Python tooltip...If you don't see the Python tooltip...

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objects

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Creating objectsCreating objectsimport bpyimport bpyfrom math import pifrom math import pi

def layer(n):def layer(n): return (n-1) * [False] + [True] + (20-n) * [False]return (n-1) * [False] + [True] + (20-n) * [False]

bpy.ops.mesh.primitive_circle_add(bpy.ops.mesh.primitive_circle_add( radius=1.0,radius=1.0, vertices=32,vertices=32, fill_type='NGON',fill_type='NGON', location=(0, 0, 0),location=(0, 0, 0), rotation=(pi/2, 0, 0))rotation=(pi/2, 0, 0))bpy.ops.object.transform_apply(rotation=True)bpy.ops.object.transform_apply(rotation=True)

base_circle = bpy.context.scene.objects.activebase_circle = bpy.context.scene.objects.activebase_circle.name = 'base_circle'base_circle.name = 'base_circle'base_circle.data.name = 'base_circle'base_circle.data.name = 'base_circle'

# Add material# Add materialbpy.ops.object.material_slot_add()bpy.ops.object.material_slot_add()mat = bpy.data.materials['circle']mat = bpy.data.materials['circle']base_circle.material_slots[0].material = matbase_circle.material_slots[0].material = mat

base_circle.layers = layer(10)base_circle.layers = layer(10)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Cloning objectsCloning objects

1) Create the cloneCreate the clone

2) Link it to the current sceneLink it to the current scene

3) Set propertiesSet properties

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Cloning objectsCloning objects

clone = base_circle.copy()clone = base_circle.copy()bpy.context.scene.objects.link(clone)bpy.context.scene.objects.link(clone)

clone.layers = layer(4)clone.layers = layer(4)clone.name = 'Circle 4'clone.name = 'Circle 4'

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

OperatorOperator

● Subclasses bpy.types.OperatorSubclasses bpy.types.Operator

● Has an identifierHas an identifier

● Can be executedCan be executed

● Can be bound to button in GUICan be bound to button in GUI

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

OperatorOperator

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

OperatorOperatorclass LoadCircleHierarchy(bpy.types.Operator):class LoadCircleHierarchy(bpy.types.Operator): bl_idname = 'import_mesh.circle_hierarchy'bl_idname = 'import_mesh.circle_hierarchy' bl_label = 'Import Bounding Circle Hierarchy'bl_label = 'Import Bounding Circle Hierarchy'

top_circle_id = bpy.props.IntProperty(top_circle_id = bpy.props.IntProperty( description='Database ID of the top-level circle')description='Database ID of the top-level circle')

circle_layer_nr = bpy.props.IntProperty(default=4)circle_layer_nr = bpy.props.IntProperty(default=4)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Operator executionOperator execution

class LoadCircleHierarchy(bpy.types.Operator):class LoadCircleHierarchy(bpy.types.Operator): bl_idname = 'import_mesh.circle_hierarchy'bl_idname = 'import_mesh.circle_hierarchy' bl_label = 'Import Bounding Circle Hierarchy'bl_label = 'Import Bounding Circle Hierarchy'

top_circle_id = bpy.props.IntProperty(top_circle_id = bpy.props.IntProperty( description='Database ID of the top-level circle') description='Database ID of the top-level circle') circle_layer_nr = bpy.props.IntProperty(default=4)circle_layer_nr = bpy.props.IntProperty(default=4) def execute(self, context):def execute(self, context): if not self.top_circle_id:if not self.top_circle_id: return {'CANCELLED'}return {'CANCELLED'} return {'FINISHED'}return {'FINISHED'}

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

RegistrationRegistration

● Operators need to be registeredOperators need to be registered

● As simple as:As simple as:

bpy.utils.register_module(__name__)bpy.utils.register_module(__name__)

at the bottom of your source file, and checking “Register”at the bottom of your source file, and checking “Register”

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

FeedbackFeedback

def execute(self, context):def execute(self, context): if not self.top_circle_id:if not self.top_circle_id: self.report({'ERROR'}, 'Loading BCH impossible, no database ID')self.report({'ERROR'}, 'Loading BCH impossible, no database ID') return {'CANCELLED'}return {'CANCELLED'} self.report({'INFO'}, 'Loading BCH finished')self.report({'INFO'}, 'Loading BCH finished') return {'FINISHED'}return {'FINISHED'}

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Extending the UIExtending the UI

● Like operator:Like operator:– extend certain class: extend certain class: bpy.types.Panelbpy.types.Panel

– set propertiesset properties

– implement methodimplement method

– register moduleregister module

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Places in the UIPlaces in the UI

● All sorts of different spots for the UI elementsAll sorts of different spots for the UI elements● bl_space_type = "VIEW_3D"bl_space_type = "VIEW_3D"

– bl_region_type = "TOOLS"bl_region_type = "TOOLS"

– bl_region_type = "TOOL_PROPS"bl_region_type = "TOOL_PROPS"

– bl_region_type = "UI"bl_region_type = "UI"

● bl_space_type = "PROPERTIES"; bl_region_type = "WINDOW"bl_space_type = "PROPERTIES"; bl_region_type = "WINDOW"– bl_context = "object"bl_context = "object"

– bl_context = "material"bl_context = "material"

– bl_context = "world"bl_context = "world"

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Extending the UIExtending the UIimport bpyimport bpy

class BoundingCircles(bpy.types.Panel):class BoundingCircles(bpy.types.Panel): bl_label = "Bounding Circles Hierarchy"bl_label = "Bounding Circles Hierarchy" bl_space_type = "PROPERTIES"bl_space_type = "PROPERTIES" bl_region_type = "WINDOW"bl_region_type = "WINDOW" bl_context = "world"bl_context = "world" def draw(self, context):def draw(self, context): … … draw stuff here …draw stuff here …

bpy.utils.register_module(__name__)bpy.utils.register_module(__name__)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Loading from a databaseLoading from a database● SQLite databaseSQLite database

– Python has built-in supportPython has built-in support

● ““circles”circles”– idid integer integer

– centre_xcentre_x, , centre_zcentre_z, , squared_radiussquared_radius real real

– sub_asub_a, , sub_bsub_b integer references circles(id) integer references circles(id)

● ““hierarchies”hierarchies”– identifieridentifier varchar(255) varchar(255)

– top_circle_idtop_circle_id integer references circles(id) integer references circles(id)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Coordinate transformationCoordinate transformation

● Our tooling is based on OgreOur tooling is based on Ogre– XZ = ground plane, Y = up XZ = ground plane, Y = up

● Load data into BlenderLoad data into Blender– XY = ground plane, Z = upXY = ground plane, Z = up

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

List hierarchies in GUIList hierarchies in GUI

● Iterate over the hierarchiesIterate over the hierarchies

● Add the identifier as a labelAdd the identifier as a label

● Add a button to load that hierarchyAdd a button to load that hierarchy

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

List hierarchies in GUIList hierarchies in GUI

import bpyimport bpyimport sqlite3import sqlite3

dbfile = bpy.path.abspath('//bounding_hierarchy.sqlite')dbfile = bpy.path.abspath('//bounding_hierarchy.sqlite')print('%s: Database file: %r' % (__name__, dbfile))print('%s: Database file: %r' % (__name__, dbfile))

class BoundingCircles(bpy.types.Panel):class BoundingCircles(bpy.types.Panel): bl_label = "Bounding Circles Hierarchy"bl_label = "Bounding Circles Hierarchy" bl_context = "world"bl_context = "world" bl_space_type = "PROPERTIES"bl_space_type = "PROPERTIES" bl_region_type = "WINDOW"bl_region_type = "WINDOW"

def draw(self, context):def draw(self, context): '''Draws the layout.''''''Draws the layout.''' db = sqlite3.connect(dbfile)db = sqlite3.connect(dbfile) try:try: self.draw_using(db)self.draw_using(db) finally:finally: db.close()db.close() def draw_using(self, db):def draw_using(self, db): '''Draws the layout using a certain database connection.''''''Draws the layout using a certain database connection.'''

layout = self.layoutlayout = self.layout

layout.label("Hierarchies in database")layout.label("Hierarchies in database") row = layout.row()row = layout.row() box = row.box()box = row.box() c = db.cursor()c = db.cursor() c.execute('select identifier, top_circle_id from hierarchies order by identifier')c.execute('select identifier, top_circle_id from hierarchies order by identifier') for dbrow in c:for dbrow in c: (identifier, top_circle_id) = dbrow(identifier, top_circle_id) = dbrow

split = box.split(percentage=0.8)split = box.split(percentage=0.8) row = split.row()row = split.row() row.label(text=identifier, translate=False)row.label(text=identifier, translate=False) # BCH Load buttons# BCH Load buttons row = split.row(align=True)row = split.row(align=True) if top_circle_id:if top_circle_id: props = row.operator("import_mesh.circle_hierarchy", text="BCH")props = row.operator("import_mesh.circle_hierarchy", text="BCH") props.top_circle_id = top_circle_idprops.top_circle_id = top_circle_id

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Loading the BCHLoading the BCH

● We know database ID of top circleWe know database ID of top circle

● Clone the base circleClone the base circle

● Do coordinate-transformation and position/scaleDo coordinate-transformation and position/scale

● Recurse over sub-circles (if any)Recurse over sub-circles (if any)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

import bpyimport bpyfrom mathutils import Vector, Matrixfrom mathutils import Vector, Matrixfrom math import pifrom math import piimport sqlite3import sqlite3

dbfile = bpy.path.abspath('//bounding_hierarchy.sqlite')dbfile = bpy.path.abspath('//bounding_hierarchy.sqlite')print('%s: Database file: %r' % (__name__, dbfile))print('%s: Database file: %r' % (__name__, dbfile))ogre2blender = Matrix.Rotation(pi / 2, 4, "X")ogre2blender = Matrix.Rotation(pi / 2, 4, "X")

def layer(n):def layer(n): return (n-1) * [False] + [True] + (20-n) * [False]return (n-1) * [False] + [True] + (20-n) * [False]

if 'base_circle' in bpy.data.objects:if 'base_circle' in bpy.data.objects: base_circle = bpy.data.objects['base_circle']base_circle = bpy.data.objects['base_circle'] bpy.context.scene.objects.active = base_circlebpy.context.scene.objects.active = base_circleelse:else: bpy.ops.mesh.primitive_circle_add(bpy.ops.mesh.primitive_circle_add( radius=1.0,radius=1.0, vertices=32,vertices=32, fill_type='NGON',fill_type='NGON', location=(0, 0, 0),location=(0, 0, 0), rotation=(pi/2, 0, 0))rotation=(pi/2, 0, 0)) bpy.ops.object.transform_apply(rotation=True)bpy.ops.object.transform_apply(rotation=True) # Set up the circle object & data names.# Set up the circle object & data names. base_circle = bpy.context.scene.objects.activebase_circle = bpy.context.scene.objects.active base_circle.name = 'base_circle'base_circle.name = 'base_circle' base_circle.data.name = 'base_circle'base_circle.data.name = 'base_circle' # Add material# Add material bpy.ops.object.material_slot_add()bpy.ops.object.material_slot_add() mat = bpy.data.materials['circle']mat = bpy.data.materials['circle'] base_circle.material_slots[0].material = matbase_circle.material_slots[0].material = mat base_circle.layers = layer(10)base_circle.layers = layer(10)

class LoadCircleHierarchy(bpy.types.Operator):class LoadCircleHierarchy(bpy.types.Operator): bl_idname = 'import_mesh.circle_hierarchy'bl_idname = 'import_mesh.circle_hierarchy' bl_label = 'Import Bounding Circle Hierarchy'bl_label = 'Import Bounding Circle Hierarchy' top_circle_id = bpy.props.IntProperty(top_circle_id = bpy.props.IntProperty( description='Database ID of the top-level circle')description='Database ID of the top-level circle') matrix = bpy.props.FloatVectorProperty(matrix = bpy.props.FloatVectorProperty( size=16,size=16, default=(default=( 1, 0, 0, 0,1, 0, 0, 0, 0, 1, 0, 0,0, 1, 0, 0, 0, 0, 1, 0,0, 0, 1, 0, 0, 0, 0, 1),0, 0, 0, 1), subtype='MATRIX',subtype='MATRIX', )) circle_layer_nr = bpy.props.IntProperty(default=4)circle_layer_nr = bpy.props.IntProperty(default=4) def execute(self, context):def execute(self, context): if not self.top_circle_id:if not self.top_circle_id: self.report({'ERROR'}, 'Loading BCH impossible, no database ID')self.report({'ERROR'}, 'Loading BCH impossible, no database ID') return {'CANCELLED'}return {'CANCELLED'} print(60 * '=')print(60 * '=') self.transf = ogre2blender * self.matrixself.transf = ogre2blender * self.matrix print('Using transformation matrix:\n%s' % self.transf)print('Using transformation matrix:\n%s' % self.transf) # Load the circles from the DB# Load the circles from the DB db = sqlite3.connect(dbfile)db = sqlite3.connect(dbfile) try:try: self.load_circle(db, self.top_circle_id)self.load_circle(db, self.top_circle_id) finally:finally: db.close()db.close() self.report({'INFO'}, 'Loading BCH %i finished' % self.top_circle_id)self.report({'INFO'}, 'Loading BCH %i finished' % self.top_circle_id) return {'FINISHED'}return {'FINISHED'}

def load_circle(self, db, circle_id, parent_circle_obj=None, depth=0):def load_circle(self, db, circle_id, parent_circle_obj=None, depth=0): # Load the circle from the DB# Load the circle from the DB c = db.cursor()c = db.cursor() c.execute('select * from circles where id=?', (circle_id, ))c.execute('select * from circles where id=?', (circle_id, )) row = c.fetchone()row = c.fetchone() # Create the circle# Create the circle radius = row[3] ** 0.5radius = row[3] ** 0.5

circle = base_circle.copy()circle = base_circle.copy() bpy.context.scene.objects.link(circle)bpy.context.scene.objects.link(circle) circle.layers = layer(self.circle_layer_nr)circle.layers = layer(self.circle_layer_nr) circle.select = Falsecircle.select = False circle.name = 'circle-%i=dbid' % circle_idcircle.name = 'circle-%i=dbid' % circle_id # Loaded in Ogre coordinates, self.transf contains ogre2blender.# Loaded in Ogre coordinates, self.transf contains ogre2blender. location = Vector((row[1], 0.03 * depth, row[2]))location = Vector((row[1], 0.03 * depth, row[2])) mat = self.transf * Matrix.Translation(location) * Matrix.Scale(radius, 4)mat = self.transf * Matrix.Translation(location) * Matrix.Scale(radius, 4) circle.matrix_local = matcircle.matrix_local = mat # Load sub-circles# Load sub-circles if row[4]:if row[4]: self.load_circle(db, row[4], circle, depth + 1)self.load_circle(db, row[4], circle, depth + 1) if row[5]:if row[5]: self.load_circle(db, row[5], circle, depth + 1)self.load_circle(db, row[5], circle, depth + 1)

return circlereturn circle

bpy.utils.register_module(__name__)bpy.utils.register_module(__name__)

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Loading the polygonLoading the polygon

● The Bounding Circle Hierarchy was based on a polygonal The Bounding Circle Hierarchy was based on a polygonal shapeshape

● This shape is also saved by our software, as OBJThis shape is also saved by our software, as OBJ

● Small modification required to place at correct layerSmall modification required to place at correct layer

● Visually nice: make polygon active objectVisually nice: make polygon active object

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

OBJ-loading & selecting operatorOBJ-loading & selecting operator

class LoadObjMesh(bpy.types.Operator):class LoadObjMesh(bpy.types.Operator): '''Imports an OBJ file and makes it the active object.''''''Imports an OBJ file and makes it the active object.''' bl_idname = 'import_mesh.obj'bl_idname = 'import_mesh.obj' bl_label = 'Imports OBJ file without prompting user'bl_label = 'Imports OBJ file without prompting user' filepath = bpy.props.StringProperty()filepath = bpy.props.StringProperty() obj_layer_nr = bpy.props.IntProperty(default=3)obj_layer_nr = bpy.props.IntProperty(default=3) def execute(self, context):def execute(self, context): bpy.ops.object.select_all(action='DESELECT')bpy.ops.object.select_all(action='DESELECT') bpy.ops.import_scene.obj(filepath=self.filepath)bpy.ops.import_scene.obj(filepath=self.filepath) bpy.context.scene.objects.active = bpy.context.selected_objects[0]bpy.context.scene.objects.active = bpy.context.selected_objects[0] bpy.context.scene.objects.active.layers = layer(self.obj_layer_nr)bpy.context.scene.objects.active.layers = layer(self.obj_layer_nr) return {'FINISHED'}return {'FINISHED'}

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Addition to GUI panel codeAddition to GUI panel code

def obj_fname_for_identifier(identifier):def obj_fname_for_identifier(identifier): fname = bpy.path.abspath('//occup_output/%s.obj' % identifier)fname = bpy.path.abspath('//occup_output/%s.obj' % identifier) return fnamereturn fname

… and in the draw() function, below the other button-drawing stuff:… and in the draw() function, below the other button-drawing stuff:

# OBJ load button# OBJ load button row = split.row(align=True)row = split.row(align=True) objfile = obj_fname_for_identifier(identifier)objfile = obj_fname_for_identifier(identifier) if os.path.exists(objfile):if os.path.exists(objfile): props = row.operator("import_mesh.obj", text="OBJ")props = row.operator("import_mesh.obj", text="OBJ") props.filepath = objfileprops.filepath = objfile

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Converting to an addonConverting to an addon

● The previous code worked only in one Blender fileThe previous code worked only in one Blender file

✔Good enough for my useGood enough for my use

✔Easy to developEasy to develop

✗ Not good for distributionNot good for distribution

✗ Can't be used in multiple filesCan't be used in multiple files

● Solution: Solution: addonaddon

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

Converting to an addonConverting to an addon

● Toss everything into one Python file …Toss everything into one Python file …

● … … or one Python moduleor one Python module

● Add a Add a bl_infobl_info dict at the top dict at the top

● Add register/unregister functionsAdd register/unregister functions

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

bl_infobl_info

bl_info = {bl_info = { "name": "Bounding Circle Hierarchy","name": "Bounding Circle Hierarchy", "author": "Sybren A. Stüvel","author": "Sybren A. Stüvel", "version": (0, 1, 1),"version": (0, 1, 1), "blender": (2, 68, 0),"blender": (2, 68, 0), "location": "World properties -> Bounding Circle Hierarchies","location": "World properties -> Bounding Circle Hierarchies", "description": "Loads BCH data from a SQLite database","description": "Loads BCH data from a SQLite database", "warning": "Research code, may not always work.","warning": "Research code, may not always work.", "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/""wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" "Scripts/SybrensBCHLoader","Scripts/SybrensBCHLoader", "category": "Object""category": "Object"}}

Guidelines at: Guidelines at: http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addonshttp://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

(un)registration(un)registration

def register():def register(): bpy.utils.register_class(BoundingCircles)bpy.utils.register_class(BoundingCircles) bpy.utils.register_class(LoadCircleHierarchy)bpy.utils.register_class(LoadCircleHierarchy) bpy.utils.register_class(LoadObjMesh)bpy.utils.register_class(LoadObjMesh)

def unregister():def unregister(): bpy.utils.unregister_module(__name__)bpy.utils.unregister_module(__name__)

# For easy testing:# For easy testing:if __name__ == '__main__':if __name__ == '__main__': register()register()

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

InstallationInstallation

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

RecapRecap

● We have seen how to:We have seen how to:– create objects from Pythoncreate objects from Python

– create operatorscreate operators

– extend the user interfaceextend the user interface

– obtain data from outside Blenderobtain data from outside Blender

– create an addoncreate an addon

● I hope you enjoyed it!I hope you enjoyed it!

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

My questions to youMy questions to you

● Setting parent object while keeping transformation matrixSetting parent object while keeping transformation matrix● Re-use of GUI elements?Re-use of GUI elements?● Custom property types?Custom property types?

– Object reference?Object reference?

● Custom editor type?Custom editor type?● Creating new objects in game engine?Creating new objects in game engine?

Sybren A. Stüvel - [email protected] A. Stüvel - [email protected] Blender as research tool: Blender as research tool: from data to visualizationfrom data to visualization Blender conference 2013Blender conference 2013

LinksLinks

● http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbohttp://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Interfaceok/Code_snippets/Interface

● http://www.blender.org/documentation/blender_python_api_http://www.blender.org/documentation/blender_python_api_2_69_1/2_69_1/

● http://stuvel.eu/http://stuvel.eu/● http://stuvelfoto.nl/http://stuvelfoto.nl/● http://vhtlab.nl/http://vhtlab.nl/