5
$\begingroup$

Just starting with scripting in Blender, and the simplest thing seems to not work as I would expect.

I copied the code that creates the standard cube and repeated it, with a z scale factor of 4. I expected this to create a "tall cube" (cuboid) that's 4 times taller than the standard cube, but that's not the case. If the standard cube is 2m x 2m x 2m, the other one is 1m x 1m x 4m (half of what I would expect).

Furthermore, the Item's transform panel says the dimensions are 1x1x4 and the scale is (1,1,1).

Any tips on understanding how that works? The API documentation is really minimal.

Here's a screenshot of the result: screenshot

Also, here's the code:

import bpy

bpy.context.area.type = 'VIEW_3D'
bpy.ops.view3d.snap_cursor_to_center()

# Create the default cube
bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, 
    align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
bpy.context.object.name = 'Standard'
    
# Like above with z-scale=4.
bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False,
    align='WORLD', location=(4, 0, 0), scale=(1, 1, 4))
bpy.context.object.name = 'Tall'

bpy.context.area.type = 'TEXT_EDITOR'
$\endgroup$

1 Answer 1

5
$\begingroup$

My suggestion is don't use it.

Can see reason for confusion, have personally never used the scale value in the operator, (fortunately because yeah it's bloody confusing) Speculate there could be some legacy nature about it.

Crunch any operator into the python console auto complete Tab will show defaults of an operator

>>> bpy.ops.mesh.pri<Tab>mitive_cu<Tab>be_add(
primitive_cube_add()
bpy.ops.mesh.primitive_cube_add(
        size=2, 
        calc_uvs=True, 
        enter_editmode=False, 
        align='WORLD', 
        location=(0, 0, 0), 
        rotation=(0, 0, 0), 
        scale=(0, 0, 0))

Construct a cube mesh

There is no need to pass any default to an operator.

One would suggest the default for scale should really be (1, 1, 1), notice too how scale is not used in the operators panel

enter image description here

Let's run some tests to see what we get for different size scale combos...

import bpy

tests = (
    (0, (1, 1, 1)),
    (1, (0, 0, 0)),
    (1, (1, 1, 1)),
    (1, (2, 2, 2)),
    (2, (1, 1, 1)),
    (2, (2, 2, 2)),
    (1, (1, 1, 4)),
    (2, (1, 1, 4)),
    (2, (2, 2, 8)),
    )

x = 0    
for i, (size, scale) in enumerate(tests):
    # Create the default cube
    bpy.ops.mesh.primitive_cube_add(
        size=size,
        scale=scale,
        location = (x, 0, 0),
        )
    cube = bpy.context.object
    cube.name = f"Test{i}_{size}_{scale}"
    print(size, scale, cube.dimensions[:])
    x += cube.dimensions.x

and OMG or WTF the Results.

0 (1, 1, 1) (1.0, 1.0, 1.0)
1 (0, 0, 0) (0.0, 0.0, 0.0)
1 (1, 1, 1) (1.0, 1.0, 1.0)
1 (2, 2, 2) (1.0, 1.0, 1.0)
2 (1, 1, 1) (2.0, 2.0, 2.0)
2 (2, 2, 2) (2.0, 2.0, 2.0)
1 (1, 1, 4) (0.5, 0.5, 2.0)
2 (1, 1, 4) (1.0, 1.0, 4.0)
2 (2, 2, 8) (2.0, 2.0, 8.0)

size 0 has dimensions, scale 0 doesn't ... same results for.. are you still confused?

In the end comes down to don't use it.

Matrices

Onto the soapbox and suggest the use of matrices. If we wish to apply a scale of (1, 1, 4) to the default cube of known dimension (2, 2, 2) can

from mathutils import Matrix
S = Matrix.Diagonal((1, 1, 4)).to_4x4()
cube.data.transform(S)
cube.data.update() # see result in viewport.

or equivalently can create matrix via

S = Matrix.Diagonal((1, 1, 4, 1))
Sz = Matrix.Scale(4, 4, 'Z')
Sz = Matrix.Scale(4, 4, (0, 0, 1))

Matrices can also be used when creating bmesh primitives as demonstrated in How to create cylinder with varying radius at different height

$\endgroup$
3
  • $\begingroup$ Thanks, re: default parameters, I intentionally left those as I wanted the example to be as close as possible to what happens when you add a cube from the UI. I did find the defaults in docs.blender.org/api/current/…. $\endgroup$
    – Barak
    Feb 24, 2021 at 10:23
  • $\begingroup$ I understand I need to first add the cube, then manipulate it. Thanks. $\endgroup$
    – Barak
    Feb 24, 2021 at 10:24
  • $\begingroup$ Would recommend doing such. Hard to see rhyme or reason in examples shown above. Could look up the source code, suggest if a default is passed (seemingly 2 and (1, 1, 1) it is ignored in calc) but IMO not worth the hassle, as long as you know can ensure a (1, 1, 1) or default (2, 2, 2) cube every time you can transform it quite simply. Cheers. $\endgroup$
    – batFINGER
    Feb 24, 2021 at 10:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .