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
    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
    Apr 7, 2014 at 16:24
  • $\begingroup$ @ideasman42, maybe could chime in? $\endgroup$
    – zeffii
    Apr 7, 2014 at 20:33

1 Answer 1

9
$\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$ Feb 10, 2017 at 9:16
  • $\begingroup$ that's Blender 244 documentation - none of that will work directly in 2.7+ $\endgroup$
    – zeffii
    Feb 11, 2017 at 10:37

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.