7
$\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$
  • $\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 '14 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 '14 at 16:24
  • $\begingroup$ @ideasman42, maybe could chime in? $\endgroup$ – zeffii Apr 7 '14 at 20:33
6
$\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)
scene = bpy.context.scene
scene.objects.link(surface_object)

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

bpy.context.scene.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.

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