9
$\begingroup$

How can I write a script to create a NURBS surface with given control points?

I did find a helpful piece of source code that got me here:

import bpy

surfacedata = bpy.data.curves.new(name='test', type='SURFACE')
surfacedata.dimensions = '3D'
surfacedata.resolution_u = 4
surfacedata.resolution_v = 4

objectdata = bpy.data.objects.new('obj_test', surfacedata)
objectdata.location = (0,0,0)
bpy.context.scene.objects.link(objectdata)

nurbs_surface = surfacedata.splines.new('NURBS')
nurbs_surface.points.add(4)
nurbs_surface.points[0].co = (-1, -1,  0.25, 1)
nurbs_surface.points[1].co = (-1,  1, -0.25, 1)
nurbs_surface.points[2].co = ( 1, -1, -0.25, 1)
nurbs_surface.points[3].co = ( 1,  1,  0.25, 1)
nurbs_surface.order_u = 2
nurbs_surface.order_v = 2
nurbs_surface.use_endpoint_u = True
nurbs_surface.use_endpoint_v = True

However, the object that this produces is just a 1D curve in space,

test

I can check some of its properties from the python console,

>>> print(len(bpy.data.objects[2].data.splines[0].points))
5

>>> print(bpy.data.objects[2].data.splines[0].point_count_u)
5

>>> print(bpy.data.objects[2].data.splines[0].point_count_v)
1

So, I'm not sure why points has 5 elements (instead of 4), and why point_count_u and point_count_v are 5 and 1 instead of 2 and 2, respectively.

$\endgroup$
3
  • $\begingroup$ NURBS surfaces are controlled by a mesh of squares. If you add a new NURBS surface and go into Edit Mode, you'll see a 4x4 mesh of control points. In your case, you've created a 5x1 "control point mesh" (it had 1 control point by default and you added 4). Creating a mesh for an object is easy, but it might be the case that bpy doesn't (yet) give you access to this control point mesh, in which case, I can't see how you'd do this. $\endgroup$
    – Garrett
    Commented Feb 23, 2014 at 5:17
  • $\begingroup$ We seem to lack the ability to set the variables point_count_v and point_count_u too $\endgroup$
    – zeffii
    Commented Apr 7, 2014 at 16:24
  • $\begingroup$ @ideasman42, maybe could chime in? $\endgroup$
    – zeffii
    Commented Apr 7, 2014 at 20:33

1 Answer 1

12
$\begingroup$

While it's not very pretty, it is possible. This example recreates the default NURBS Surface. Inspired by https://blender.stackexchange.com/a/8587/47

import bpy
from mathutils import Vector

surface_data = bpy.data.curves.new('wook', 'SURFACE')
surface_data.dimensions = '3D'

# 16 coordinates
points = [
    Vector((-1.5, -1.5, 0.0, 1.0)), Vector((-1.5, -0.5, 0.0, 1.0)),
    Vector((-1.5, 0.5, 0.0, 1.0)), Vector((-1.5, 1.5, 0.0, 1.0)),
    Vector((-0.5, -1.5, 0.0, 1.0)), Vector((-0.5, -0.5, 1.0, 1.0)),
    Vector((-0.5, 0.5, 1.0, 1.0)), Vector((-0.5, 1.5, 0.0, 1.0)),
    Vector((0.5, -1.5, 0.0, 1.0)), Vector((0.5, -0.5, 1.0, 1.0)),
    Vector((0.5, 0.5, 1.0, 1.0)), Vector((0.5, 1.5, 0.0, 1.0)),
    Vector((1.5, -1.5, 0.0, 1.0)), Vector((1.5, -0.5, 0.0, 1.0)),
    Vector((1.5, 0.5, 0.0, 1.0)), Vector((1.5, 1.5, 0.0, 1.0))
]

# set points per segments (U * V)
for i in range(0, 16, 4):
    spline = surface_data.splines.new(type='NURBS')
    spline.points.add(3)  # already has a default vector

    for p, new_co in zip(spline.points, points[i:i+4]):
        p.co = new_co

surface_object = bpy.data.objects.new('NURBS_OBJ', surface_data)
bpy.context.collection.objects.link(surface_object)

splines = surface_object.data.splines
for s in splines:
    for p in s.points:
        p.select = True

bpy.context.view_layer.objects.active = surface_object
bpy.ops.object.mode_set(mode = 'EDIT') 
bpy.ops.curve.make_segment()

The ideal situation would be where the spline.points would take a nested list and automatically combine them under the hood, rather than requiring calls to bpy.ops.

Edit: For Blender 2.8+, linking objects uses 'bpy.context.collection'

$\endgroup$
2
  • $\begingroup$ Thanks, I should be able to get what I want out of your reply. There might also be a method using docs.blender.org/api/244PythonDoc/Curve.SurfNurb-class.html But yours looks simpler to follow for an amateur $\endgroup$ Commented Feb 10, 2017 at 9:16
  • $\begingroup$ that's Blender 244 documentation - none of that will work directly in 2.7+ $\endgroup$
    – zeffii
    Commented Feb 11, 2017 at 10:37

You must log in to answer this question.

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