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
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
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 ...?
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.
If you expand the source code, you will see the directory structure for the following.
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.
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
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
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.
Create a process to read a .blend file in Python (SOP).
I prepared a .blend with cubes and Sae Yamamoto. Sae Yamamoto is cut in half and the Mirror and Subdivision modifiers are set.
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 |
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.
When the .blend file is read by bpy, the following log is output. I didn't know how to stop this from the outside.
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