Using the API to Create and Modify 3ds Max NURBS Models

As mentioned above, 3ds Max itself uses a different internal representation of NURBS objects than the API does. The API is simply a means to access these internal 3ds Max NURBS objects and allow them to be manipulated.

The object used in communication between the internal 3ds Max NURBS objects and the classes in the SDK available to work with these objects is the NURBSSet. There are also two global functions used in this communication. These are CreateNURBSObject() and GetNURBSSet(). How these are used is described below:

Creating New NURBS Objects

The API can be used to create new NURBS objects. This is done by adding the objects (points, curves and surfaces) to an item called a NURBS 'set' and calling the global function CreateNURBSObject(). The NURBSSet is a container for the objects. Then the global function CreateNURBSObject() makes an internal 3ds Max NURBS object out of the set.

As an example, consider the following code fragment that creates a NURBSCVCurve object (with NURBSControlVertex sub-objects) and puts it in the scene:

// Create an empty NURBSSet object
NURBSSet nset;
 
// Allocate a new NURBSCVCurve and set the knots and CVs
NURBSCVCurve *c = new NURBSCVCurve();
c->SetName(_T("CV Curve"));
c->SetNumCVs(4);
c->SetOrder(4);
c->SetNumKnots(8);
for (int k = 0; k < 4; k++)
{
   c->SetKnot(k, 0.0);
   c->SetKnot(k+4, 1.0);
}
 
NURBSControlVertex cv;
cv.SetPosition(0, Point3(0, 0, 50));
c->SetCV(0, cv);
cv.SetPosition(0, Point3(-100, 0, 50));
c->SetCV(1, cv);
cv.SetPosition(0, Point3(-100, 100, 50));
c->SetCV(2, cv);
cv.SetPosition(0, Point3(0, 100, 50));
c->SetCV(3, cv);
 
// Add the NURBSCVCurve object to the set
nset.AppendObject(c);
 
// Create the NURBS object from the NURBSSet
Matrix3 mat(1);
Object *obj = CreateNURBSObject(ip, &nset, mat);
 
// Create the node in the scene and point it at the NURBS object
INode *node = ip->CreateObjectNode(obj);
node->SetName(_T("NURBS Set 1"));

The NURBS object created (obj) will have the Class_ID: EDITABLE_SURF_CLASS_ID.

Modifying Existing NURBS Objects

The API can also be used to modify the properties of existing NURBS objects in the scene. To gain access to an internal 3ds Max NURBS object you must have the data copied into a NURBSSet. This is done using the global function GetNURBSSet(). You can then use the methods of the NURBSSet to access the objects. After checking the type of the object you can cast it to the appropriate class and use that class's methods to alter the item.

For example, the following sample code attempts to grab the first NURBS sub-object from the first node in the current selection set. It then checks if it's a blend surface and if so adjust one of the tension parameters.

// Get the first selected node
INode* node = ip->GetSelNode(0);
if (!node) return;
 
// Get the object reference of the node
Object* obj = node->GetObjectRef();
 
// Make sure it's a NURBS object
if (obj->ClassID() == EDITABLE_SURF_CLASS_ID)
{
   NURBSSet getSet;
   BOOL okay = GetNURBSSet(obj, ip->GetTime(), getSet, TRUE);
   if (okay)
   {
      NURBSObject *nObj;
     nObj = getSet.GetNURBSObject(0), ip->GetTime());
     if (nObj->GetType() == kNBlendSurface)
     {
      // It's a blend, adjust the tension
      NURBSBlendSurface *bSurf = ( NURBSBlendSurface *)nObj;
      bSurf->SetTension(ip->GetTime(), 0, 2.0);
     }
   }
}

There are other global functions that may be used to modify NURBS objects. These functions are documented at the end of this topic. For instance, developers can use the function BreakSurface() to take an existing NURBS surface and break it into two separate surfaces.