Blender Python API in Houdini (Python 3)

Python 3 becomes Production Builds in Houdini 18.5

Houdini 18.5 --Python 3 has been added to Production Builds Items. Now that you can use Python3, you should be able to use libraries that are only available in Python3 series! So this time I will put bpy (Blender Python) that can be used in Python 3.7 into Houdini.

I used the following Windows version of Houdini. houdini-py3-18.5.351-win64-vc141.exe

build bpy

Since bpy as a Python Module is not currently distributed, you need to build it from the source code referring to the following. Building Blender as a Python Module

Establish a build environment

You can find a Japanese article about building Blender from source code immediately by searching, so if you need more information, please look there.

Maybe it should be okay if the area is installed ...?

Drop the source code

I will drop the source code by referring to https://developer.blender.org/diffusion/B/. I think you can zip it from the mirror on github.

Build

If you expand the source code, you will see the directory structure for the following. blender_build.PNG

Open a command prompt in this directory (where make.bat is)

make bpy

When you execute, other libraries required for build will be dropped by Subversion and built. (As soon as you start, you'll be asked if you want to drop the other libraries you need, so press y to proceed). The first time will take a lot of time.

Arrange build artifacts for reading in Houdini

Build artifacts (Blender source code directory) \ .. \ build_windows_Bpy_x64_vc16_Release \ bin \ Release It is in.

bpy.pyd, libfftw3-3.dll Place these two in a Houdini python-readable directory. The required dlls may increase or decrease as the blender version changes. Here, it is arranged below. C: \ Users \ (username) \ Documents \ houdini18.5 \ python3.7libs

37libs.PNG

2.90 (built blender version) folder

Place this folder in the directory where the installed Houdini exe is located. Setting environment variables may help elsewhere (unverified). Here, it is arranged below. C:\Program Files\Side Effects Software\Houdini 18.5.351\bin bin.PNG

Use Blender Python API

Confirm import bpy

It's finally ready to use. Make sure that ʻimport bpy` can be executed without error in Python Shell or Python (SOP). If there is a problem with the build artifact or location, you will get an error or Houdini will crash.

python_shell.PNG

Read .blend file

Create a process to read a .blend file in Python (SOP).

Preparation of test data

I prepared a .blend with cubes and Sae Yamamoto. Sae Yamamoto is cut in half and the Mirror and Subdivision modifiers are set. test_data.PNG

Write Python code in Python (SOP)

Name in the Primitive attribute N, uv with Vertex attributes I wrote the code to read.

The parameters are as follows.

Label Name Description
Blender File blend_file Read.Specify blend
Object Name objects Specifying the object to read
Apply Modifier apply_modifier Specify whether to apply the modifier

houdini.PNG

import os
import bpy
from bpy_extras.io_utils import axis_conversion

node = hou.pwd()
geo = node.geometry()

#Prepare the attributes to set
name_attrib = geo.addAttrib(hou.attribType.Prim, 'name', '')
normal_attrib = geo.addAttrib(hou.attribType.Vertex, 'N', (0.0, 0.0, 0.0))
uv_attrib = geo.addAttrib(hou.attribType.Vertex, 'uv', (0.0, 0.0, 0.0))

#Parameter reading
blend_file = node.parm('blend_file').evalAsString()
apply_modifier = node.parm('apply_modifier').evalAsInt()
object_names = [ s.strip() for s in node.parm('objects').evalAsString().split() ]

if len(blend_file)>0:
    # .Open blend
    bpy.ops.wm.open_mainfile(filepath=blend_file)
    #Read all objects if no name is set
    if len(object_names)==0:
        object_names = bpy.data.objects.keys()
else:
    #Open the initial file of blender and put out Susanne
    bpy.ops.wm.read_homefile(app_template='')
    bpy.ops.mesh.primitive_monkey_add()
    object_names = ['Suzanne']

depsgraph = bpy.context.evaluated_depsgraph_get()
#A matrix that transforms the blender axis orientation to the Houdini axis orientation
axis_conv_mat = axis_conversion(
    from_forward='-Y', from_up='Z',  
    to_forward='Z', to_up='Y'
    ).to_4x4()
    
#Opens an object with the specified name
for obj_name in object_names:
    obj = bpy.data.objects[obj_name]
    if obj.type!='MESH':
        continue
    
    #Apply modifiers if needed
    ob_for_convert = obj.evaluated_get(depsgraph) if apply_modifier else obj.original

    #Extract mesh from object
    try:
        me = ob_for_convert.to_mesh()
    except:
        me = None
    if me is None:
        continue
        
    #Apply axis transformations and object transforms to meshes
    me.transform( axis_conv_mat @ obj.matrix_world )
    
    #What to do if a negative scale is applied
    if obj.matrix_world.determinant() < 0.0:
        me.flip_normals()
    
    #Calculate Vertex Normal
    me.calc_normals_split()

    #Get UV data
    uv_layer = me.uv_layers.active.data[:] if len(me.uv_layers) > 0 else None

    #Create points
    points = [ hou.Vector3(v.co) for v in me.vertices ]
    pt_list = geo.createPoints(points)

    #Since the vertex order of polygons is different between blender and houdini, convert
    loop_indices_list = list()
    for mpoly in me.polygons:
        count = len(mpoly.loop_indices)
        loop_indices_list.append( [ mpoly.loop_indices[(count-i)%count] for i in range(0, count) ] )

    for loop_indices in loop_indices_list:
        poly = geo.createPolygon()
        poly.setAttribValue(name_attrib, obj_name)
        for i in loop_indices:
            #Make polygons
            v = poly.addVertex( pt_list[ me.loops[i].vertex_index ] )
            # N attribute 
            v.setAttribValue(normal_attrib,  me.loops[i].normal)
            # uv attribute 
            if uv_layer:
                uv = uv_layer[i].uv
                v.setAttribValue(uv_attrib, (uv[0], uv[1], 0.0))

The Object Name parameter can be selected from ▽ in Menu Script as shown below.

import os
import bpy

name_list = list()

node = hou.pwd()
blend_file = node.parm('blend_file').evalAsString()
#File existence check
if not os.path.exists(blend_file):
    return name_list

#Enumerate the names of Mesh objects
objects = bpy.data.objects
for obj in objects:
    if obj.type == 'MESH':
        name_list.extend( [obj.name]*2 )

return name_list

I'm writing a comment in the code, so I won't explain it in detail. The code to get the mesh information in Blender Python API (Blender installation directory) \ (Blender version) \ scripts \ addons Below, the ones that start with io_ are Importer / Exporter add-ons, so that will be helpful. The code of ↑ was written with reference to io_scene_obj.

Other

When the .blend file is read by bpy, the following log is output. I didn't know how to stop this from the outside. houdini_console.png

If it is in the way, comment out this log output code when building bpy and it will not be output.

source\blender\blenkernel\intern\blendfile.c


int BKE_blendfile_read(bContext *C,
                       const char *filepath,
                       const struct BlendFileReadParams *params,
                       ReportList *reports)
{
  BlendFileData *bfd;
  bool success = false;

  /* Don't print startup file loading. */
  if (params->is_startup == false) {
    printf("Read blend: %s\n", filepath);
  }
  ...
}

Recommended Posts

Blender Python API in Houdini (Python 3)
Evernote API in Python
Python interpreter in Maya, Houdini, blender, Nuke
C API in Python 3
Hit Mastodon's API in Python
Generate 8 * 8 (64) cubes in Blender Python
Draw Sine Waves in Blender Python
Getting the arXiv API in Python
Hit the Sesami API in Python
Create Gmail in Python without API
Hit the web API in Python
Quickly implement REST API in Python
Access the Twitter API in Python
Get started with Python in Blender
Quadtree in Python --2
Python in optimization
CURL in python
Mouse operation using Windows API in Python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Try using the Wunderlist API in Python
Meta-analysis in Python
Try using the Kraken API in Python
Unittest in python
Epoch in Python
Discord in Python
Blender 2.9 Python Extrude extrude
Get Google Fit API data in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
Get Youtube data in Python using Youtube Data API
Plink in Python
Constant in python
To reference environment variables in Python in Blender
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Try hitting the YouTube API in Python
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python