1
$\begingroup$

I have been googling for a way to interrogate the 3d view using a script, to discover the locations of the faces of a cube. I have seen a lot of rather complex, daunting sample scripts creating cubes from scratch with primitives (vertex creation etc) but so far nothing that looks simple. If I have selected a cube successfully, as below:

ob = bpy.data.objects['Cube_7_7']
ob.select = True
bpy.context.scene.objects.active = ob
bpy.ops.object.mode_set(mode='EDIT')

(the intended cube lights up when selected and goes into edit mode, so I must have at least this basic syntax right)

How can I find out, say, the median point of the bottom face of this cube? is this straightforward (i.e. is there a face naming convention relative to the cube's position at its creation)... or is it ugly? basically, I want to identify the bottom faces of all my cubes.

$\endgroup$
  • 2
    $\begingroup$ It's not THAT straightforward I'd say. In a polygon model, each face has a unique index number, but the order of indicies depends on how the cube had been created and what the object orientation is. So it's not a reliable technique, unless you can guarantee that all cubes are absolutely identical. The other method would involve calculating the center of gravity of each face using its world matrix, and picking the face with the lowest center. $\endgroup$ – aliasguru Jan 3 '17 at 7:37
  • 1
    $\begingroup$ Use the daunting examples you found. If you're unhappy with them, link them in the post and explain what the problem is. $\endgroup$ – Leander Jan 3 '17 at 10:52
3
$\begingroup$

This script should find the bottom face of the cube, not taking into consideration the cubes rotation.

import bpy
import bmesh

cube = bpy.context.active_object

bm = bmesh.new()
bm.from_mesh(cube.data)

minZ = float('inf')
for face in bm.faces:
    if face.calc_center_bounds()[2] < minZ:
        minZ = face.calc_center_bounds()[2]
        bottom_face = face

cube.data.polygons[bottom_face.index].select = True
print('The bottom face is '+str(bottom_face))

Thus, you will need to either apply rotation (Ctrl + A) to all cubes or use the global Z, like this

import bpy
import bmesh

cube = bpy.context.active_object

bm = bmesh.new()
bm.from_mesh(cube.data)

minZ = float('inf')
for face in bm.faces:
    Z = (cube.matrix_world * face.calc_center_bounds())[2] ## This line is different
    if Z < minZ:
        minZ = Z
        bottom_face = face

cube.data.polygons[bottom_face.index].select = True
print(bottom_face)       

EDIT: Simpler code without using bmesh

import bpy

cube = bpy.context.active_object
mesh = cube.data

minZ = float('inf')
for face in mesh.polygons:
    Z = face.center[2]
    if Z < minZ:
        minZ = Z
        bottom_face = face

bottom_face.select = True
print('The bottom face is '+str(bottom_face))

for global coordinates replace the line

Z = face.center[2]

with

Z = (cube.matrix_world * face.center)[2]
$\endgroup$
  • $\begingroup$ many thanks for beginner-friendly code sample qwazix. these cubes have just been created and have no rotation during the phase of construction when I need to know where those bottom faces are; I plan to parent another mesh to them at that point, and if they rotate later, the parented object should just follow along... at least, I hope so! $\endgroup$ – Tazling Jan 3 '17 at 20:18
  • $\begingroup$ Notice that to see the selected faces you have to deselect them all, exit to object mode, run the script and enter edit mode again. This is due to the limitation of the select attribute in blender, but since you don't actually need to select them but do other things with them I left it just for demonstration purposes. $\endgroup$ – qwazix Jan 3 '17 at 20:32
  • $\begingroup$ @Tazling I just found out that it's possible without using bmesh, thus simplifying the code. I thought that object.data doesn't expose faces but it just actually calls them polygons $\endgroup$ – qwazix Jan 3 '17 at 20:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.