Ejemplo n.º 1
0
// This function creates a cylinder similarly to the teapot
// and the torus above. This time the cylinder is trimmed with
// a circle defined by 9 square-based control points to show
// an example of defining a circle without using infinite control
// points (see [Piegl and Tiller], pp. 299, Ex7.2 (Figure 7.16)) as
// well as to show how to define a rational trimming curve.
NodePtr makeTrimmedCylinder()
{
    SimpleMaterialPtr cylmat =  SimpleMaterial::create();
    beginEditCP(cylmat);
    {
        cylmat->setDiffuse(  Color3f(0.0, 0.8, 0.7));
        cylmat->setAmbient(  Color3f(0.2, 0.2, 0.2));
        cylmat->setEmission( Color3f(0.02, 0.02, 0.02) );
        cylmat->setSpecular( Color3f(0.78, 0.78, 0.78) );
        cylmat->setShininess( 128 );
        cylmat->addChunk(g_fb_chunk);
    }
    endEditCP(cylmat);
    float knots4[4] = {0, 0, 1, 1};
    float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
    float knots_outertrim[7] = {0, 0, 1, 2, 3, 4, 4};
    float knots_trimcircle[12] = {0, 0, 0, 0.25, 0.25, 0.5,
                                  0.5, 0.75, 0.75, 1, 1, 1
                                 };
    float cylcps[10][4] = {
        { 1.00,     0, -.50, 1},
        { 1.00,     0,  .50, 1},
        {    0,  1.00,    0, 0},
        {    0,  1.00,    0, 0},
        {-1.00,     0, -.50, 1},
        {-1.00,     0,  .50, 1},
        {    0, -1.00,    0, 0},
        {    0, -1.00,    0, 0},
        { 1.00,     0, -.50, 1},
        { 1.00,     0,  .50, 1},
    };
    float outertrim_cps[5][2] = {
        {0, 0},
        {1, 0},
        {1, 1},
        {0, 1},
        {0, 0},
    };
    float trimcircle_cps[9][3] = {
        {0.541667, 0.5,      1},
        {0.383016, 0.235702, 0.707107},
        {0.5,      0.333333, 1},
        {0.324091, 0.235702, 0.707107},
        {0.458333, 0.5,      1},
        {0.324091, 0.471405, 0.707107},
        {0.5,      0.666667, 1},
        {0.383016, 0.471405, 0.707107},
        {0.541667, 0.5,      1},
    };
    NodePtr cylnode = makeSurface(10, cylcps, 2, 1, 8, knots_circle,
                                  4, knots4, 0.001, cylmat);
    SurfacePtr s = SurfacePtr::dcast(cylnode->getCore());
    // add outer trimming around the domain
    addTrimCurve(s, 5, outertrim_cps, 1, 7, knots_outertrim, true);
    // add inside circle trimming
    addTrimCurve(s, 9, trimcircle_cps, 2, 12, knots_trimcircle, true);
    return cylnode;

}
Ejemplo n.º 2
0
// This function creates a torus from a single NURBS surface
// using only 25 control points (of which 12 are unique).
// Similarly to the teapot, this uses the half-circle
// constructed from 3 control points (of which the middle point
// is infinite) which is then mirrored to form a full circle.
// (See the NURBS book [Piegl and Tiller], pp. 296, Ex7.1 (Figure 7.15)
// for details on the half-circle.)
NodePtr makeTorus()
{
    SimpleMaterialPtr torusmat =  SimpleMaterial::create();
    beginEditCP(torusmat);
    {
        torusmat->setDiffuse(  Color3f(1.0, 0.0, 0.2));
        torusmat->setAmbient(  Color3f(0.2, 0.2, 0.2));
        torusmat->setEmission( Color3f(0.02, 0.02, 0.02) );
        torusmat->setSpecular( Color3f(0.78, 0.78, 0.78) );
        torusmat->setShininess( 128 );
        torusmat->addChunk(g_fb_chunk);
    }
    endEditCP(torusmat);
    float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
    float toruscps[25][4] = {
        { 1.00,     0,  .75, 1}, //
        {  .25,     0,    0, 0}, //
        { 1.00,     0, 1.25, 1}, //
        { -.25,     0,    0, 0}, //
        { 1.00,     0,  .75, 1},
        {    0,  1.00,    0, 0}, //
        {    0,   .25,    0, 0}, //
        {    0,  1.00,    0, 0},
        {    0,  -.25,    0, 0}, //
        {    0,  1.00,    0, 0},
        {-1.00,     0,  .75, 1}, //
        { -.25,     0,    0, 0}, //
        {-1.00,     0, 1.25, 1}, //
        {  .25,     0,    0, 0}, //
        {-1.00,     0,  .75, 1},
        {    0, -1.00,    0, 0}, //
        {    0,  -.25,    0, 0},
        {    0, -1.00,    0, 0},
        {    0,   .25,    0, 0},
        {    0, -1.00,    0, 0},
        { 1.00,     0,  .75, 1},
        {  .25,     0,    0, 0},
        { 1.00,     0, 1.25, 1},
        { -.25,     0,    0, 0},
        { 1.00,     0,  .75, 1},
    };
    NodePtr torus = makeSurface(25, toruscps, 2, 2, 8, knots_circle,
                                8, knots_circle, 0.005, torusmat);
    return torus;
}
Ejemplo n.º 3
0
void CharacterModel::convertMaterials(std::string configfile)
{
    getMaterials().clear();
    UInt32 mcnt = 0;
    PathHandler ph;
    
    ph.setBaseFile(configfile.c_str());
       
    for(int mid = 0; mid < _coreModel->getCoreMaterialCount(); mid++)
    {
        CalCoreMaterial *coremat = _coreModel->getCoreMaterial(mid);
        SimpleMaterialPtr mat = SimpleMaterial::create();

        beginEditCP(mat);

        CalCoreMaterial::Color &calamb = coremat->getAmbientColor();
        CalCoreMaterial::Color &caldif = coremat->getDiffuseColor();
        CalCoreMaterial::Color &calspec = coremat->getSpecularColor();

        mat->setAmbient(Color3f(calamb.red / 255.0f, calamb.green / 255.0f, calamb.blue / 255.0f));
        mat->setDiffuse(Color3f(caldif.red / 255.0f, caldif.green / 255.0f, caldif.blue / 255.0f));
        mat->setSpecular(Color3f(calspec.red / 255.0f, calspec.green / 255.0f, calspec.blue / 255.0f));
        
        mat->setShininess(coremat->getShininess() * 100.f);
        mat->setLit(true);
        mat->setColorMaterial(GL_NONE);
        
        for(int mapId = 0; mapId < coremat->getMapCount(); mapId++)
        {
            std::string file = coremat->getMapFilename(mapId);
            std::string pfile = ph.findFile(file.c_str());
            SINFO << "Loading texture '" << pfile << "'..." << endLog;

            ImagePtr img = Image::create();
            
             if(!img->read(pfile.c_str()))
            {
                SWARNING << "CharacterModel::convertMaterials: error "
                         << "loading image " << file << endLog;
            }
            else
            {
                // amz with my test scene paladin.cfg all textures were
                // upside down so I disabled the vertical flipping perhaps
                // they fixed the bug in Cal3D?
#if 0
                beginEditCP(img);
                {
                // For some reason Cal3D expects textures upside down ???
                UInt32 bpl = img->getBpp() * img->getWidth();
                UChar8 *t = img->getData(), 
                       *b = t + (img->getHeight() - 1) * bpl,
                        dum;

                for(UInt32 y = img->getHeight() / 2; y > 0; --y)
                {
                    for(UInt32 x = bpl; x > 0; --x, ++t, ++b)
                    {
                        dum = *t;
                        *t = *b;
                        *b = dum;
                    }
                    b -= bpl * 2;
                }
                }
                endEditCP(img);
#endif
                
                TextureChunkPtr tex = TextureChunk::create();
                
                beginEditCP(tex);
                tex->setImage(img);
                tex->setEnvMode(GL_MODULATE);
                endEditCP(tex);
                
                mat->addChunk(tex);
            }
        }
            
        endEditCP(mat);
        
        coremat->setUserData((Cal::UserData)mcnt);
        getMaterials().push_back(mat);
        mcnt ++;
    }    
}
Ejemplo n.º 4
0
int main(int argc, char **argv)
{
    osgInit(argc,argv);

    // GLUT init
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    
    glutCreateWindow("OpenSG");
    
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);

    PassiveWindowPtr pwin=PassiveWindow::create();
    pwin->init();   
    
    // create the texture
    tx1 = TextureChunk::create();
   
    const UInt16 width = 16, height = 1;
    
    ImagePtr pImg1 = Image::create();
    pImg1->set(Image::OSG_RGB_PF, width, height );
    
    beginEditCP(pImg1);
    UInt8 *d = pImg1->editData();
    
    for(UInt16 y = 0; y < height; ++y)
    {
        for(UInt16 x = 0; x < width; ++x)
        {
            *d++ = static_cast<UInt8>(x * 255.f / width);
            *d++ = static_cast<UInt8>(y * 255.f / height);
            *d++ = static_cast<UInt8>(128);
        }
    }
    endEditCP(pImg1);
    
    
    beginEditCP(tx1);
    tx1->setImage(pImg1); 
    tx1->setMinFilter(GL_NEAREST);
    tx1->setMagFilter(GL_NEAREST);
    tx1->setWrapS(GL_REPEAT);
    tx1->setWrapT(GL_REPEAT);
    endEditCP(tx1);

    tg = TexGenChunk::create();
    
    beginEditCP(tg);
    tg->setGenFuncS(GL_EYE_LINEAR);
    tg->setGenFuncSPlane(Vec4f(0,.15,0,0));
    endEditCP(tg);
    
  
    // create the material
    SimpleMaterialPtr mat = SimpleMaterial::create();
    
    beginEditCP(mat);
    mat->setDiffuse(Color3f(1,1,1));
    mat->setLit(false);
    mat->addChunk(tx1);
    mat->addChunk(tg);
    endEditCP(mat);
    
    // create the scene

    NodePtr torus = makeTorus( .5, 2, 16, 32 );

    GeometryPtr geo = GeometryPtr::dcast(torus->getCore());
    
    beginEditCP(geo, Geometry::MaterialFieldMask);
    geo->setMaterial(mat);
    endEditCP(geo, Geometry::MaterialFieldMask);
      
    transn1 = makeCoredNode<Transform>(&trans1);
    beginEditCP(transn1, Node::CoreFieldMask | Node::ChildrenFieldMask);
    {
        transn1->addChild(torus);
    }
    endEditCP  (transn1, Node::CoreFieldMask | Node::ChildrenFieldMask);


    transn2 = makeCoredNode<Transform>(&trans2);

    NodePtr scene = makeCoredNode<Group>();  
    beginEditCP(scene);
    scene->addChild(transn1);
    scene->addChild(transn2);
    endEditCP(scene);
    
    beginEditCP(tg);
    tg->setSBeacon(torus);
    endEditCP(tg);
    
    // create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // create the window and initial camera/viewport
    mgr->setWindow(pwin );
    // tell the manager what to manage
    mgr->setRoot  (scene);
    
    // show the whole scene
    mgr->showAll();
    mgr->redraw();

    webInterface = new WebInterface();
    webInterface->setRoot(scene);
    
    // GLUT main loop
    glutMainLoop();

    return 0;
}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
    osgInit(argc,argv);

    // GLUT init
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);

    glutCreateWindow("OpenSG");

    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);

    PassiveWindowPtr pwin=PassiveWindow::create();
    pwin->init();

    // create the scene
    NodePtr scene;

    scene = Node::create();

    // create the material

    // Pass 1: Simple red, shiny, depth-tested

    DepthChunkPtr cl1 = DepthChunk::create();
    beginEditCP(cl1);
    cl1->setEnable(true);
    cl1->setFunc(GL_LEQUAL);
    endEditCP(cl1);

    SimpleMaterialPtr mat = SimpleMaterial::create();
    beginEditCP(mat);
    mat->setDiffuse(Color3f(1,0,0));
    mat->setSpecular(Color3f(.9,.9,.9));
    mat->setShininess(30);
    mat->setLit(true);
    mat->addChunk(cl1);
    endEditCP(mat);

    // Pass 2: Green unlit, without depth testing

    DepthChunkPtr cl2 = DepthChunk::create();
    beginEditCP(cl2);
    cl2->setEnable(false);
    endEditCP(cl2);

    SimpleMaterialPtr mat2 = SimpleMaterial::create();
    beginEditCP(mat2);
    mat2->setDiffuse(Color3f(0,1,0));
    mat2->setLit(false);
    mat2->setTransparency(.8);
    mat2->addChunk(cl2);
    endEditCP(mat2);

    // Bring them together

    MultiPassMaterialPtr mpm = MultiPassMaterial::create();

    beginEditCP(mpm);
    mpm->editMFMaterials()->push_back(mat);
    mpm->editMFMaterials()->push_back(mat2);
    endEditCP(mpm);

    GeometryPtr g1 = makeTorusGeo(0.2, 2, 8, 16);

    beginEditCP(scene);
    scene->setCore(g1);
    endEditCP(scene);

    beginEditCP(g1);

    g1->setMaterial(mpm);

    endEditCP(g1);

    // create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // create the window and initial camera/viewport
    mgr->setWindow(pwin );
    // tell the manager what to manage
    mgr->setRoot  (scene);

    // show the whole scene
    mgr->showAll();
    mgr->redraw();

    // GLUT main loop
    glutMainLoop();

    return 0;
}
Ejemplo n.º 6
0
// This function creates the classic Utah teapot from 4 NURBS
// surfaces: one surface each for the lid, body, handle and spout.
// The "classic" representation is using 18 rational Bezier patches,
// but in order to show the construction of more complex surfaces
// these have been combined into as few NURBS surfaces as possible.
NodePtr makeTeapot()
{
    SimpleMaterialPtr teapotmat =  SimpleMaterial::create();
    beginEditCP(teapotmat);
    {
        teapotmat->setDiffuse(  Color3f(0.8, 0.8, 0.8));
        teapotmat->setAmbient(  Color3f(0.2, 0.2, 0.2));
        teapotmat->setEmission( Color3f(0.02, 0.02, 0.02) );
        teapotmat->setSpecular( Color3f(0.78, 0.78, 0.78) );
        teapotmat->setShininess( 128 );
        teapotmat->addChunk(g_fb_chunk);
    }
    endEditCP(teapotmat);
    NodePtr teapotroot = makeCoredNode<Group>();
    float knots11[11] = {0, 0, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 1};
    float knots14[14] = {0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3};
    float knots_circle[8] = {0, 0, 0, 0.5, 0.5, 1, 1, 1};
    float lidcps[35][4] = {
        { 0.0000, 4.0000, 0.0000, 1.0000},
        { 0.0000, 4.0000, 0.8000, 1.0000},
        { 0.0000, 3.6000, 0.0000, 1.0000},
        { 0.0000, 3.4000, 0.2000, 1.0000},
        { 0.0000, 3.2000, 0.4000, 1.0000},
        { 0.0000, 3.2000, 1.3000, 1.0000},
        { 0.0000, 3.0000, 1.3000, 1.0000},

        {-0.0000, 0.0000, 0.0000, 0.0000},
        {-0.8000, 0.0000, 0.0000, 0.0000},
        {-0.0000, 0.0000, 0.0000, 0.0000},
        {-0.2000, 0.0000, 0.0000, 0.0000},
        {-0.4000, 0.0000, 0.0000, 0.0000},
        {-1.3000, 0.0000, 0.0000, 0.0000},
        {-1.3000, 0.0000, 0.0000, 0.0000},

        { 0.0000, 4.0000,-0.0000, 1.0000},
        { 0.0000, 4.0000,-0.8000, 1.0000},
        { 0.0000, 3.6000,-0.0000, 1.0000},
        { 0.0000, 3.4000,-0.2000, 1.0000},
        { 0.0000, 3.2000,-0.4000, 1.0000},
        { 0.0000, 3.2000,-1.3000, 1.0000},
        { 0.0000, 3.0000,-1.3000, 1.0000},

        { 0.0000, 0.0000, 0.0000, 0.0000},
        { 0.8000, 0.0000, 0.0000, 0.0000},
        { 0.0000, 0.0000, 0.0000, 0.0000},
        { 0.2000, 0.0000, 0.0000, 0.0000},
        { 0.4000, 0.0000, 0.0000, 0.0000},
        { 1.3000, 0.0000, 0.0000, 0.0000},
        { 1.3000, 0.0000, 0.0000, 0.0000},

        { 0.0000, 4.0000, 0.0000, 1.0000},
        { 0.0000, 4.0000, 0.8000, 1.0000},
        { 0.0000, 3.6000, 0.0000, 1.0000},
        { 0.0000, 3.4000, 0.2000, 1.0000},
        { 0.0000, 3.2000, 0.4000, 1.0000},
        { 0.0000, 3.2000, 1.3000, 1.0000},
        { 0.0000, 3.0000, 1.3000, 1.0000},
    };
    NodePtr lid = makeSurface(35, lidcps, 2, 3, 8, knots_circle,
                              11, knots11, 0.005, teapotmat);
    float bodycps[50][4] = {
        { 0.0000, 3.0000, 1.4000, 1.0000},
        { 0.0000, 3.1750, 1.3375, 1.0000},
        { 0.0000, 3.1750, 1.4375, 1.0000},
        { 0.0000, 3.0000, 1.5000, 1.0000},
        { 0.0000, 2.3000, 1.7500, 1.0000},
        { 0.0000, 1.6000, 2.0000, 1.0000},
        { 0.0000, 1.0000, 2.0000, 1.0000},
        { 0.0000, 0.4000, 2.0000, 1.0000},
        { 0.0000, 0.2000, 1.5000, 1.0000},
        { 0.0000, 0.0000, 1.5000, 1.0000},

        {-1.4000, 0.0000, 0.0000, 0.0000},
        {-1.3375, 0.0000, 0.0000, 0.0000},
        {-1.4375, 0.0000, 0.0000, 0.0000},
        {-1.5000, 0.0000, 0.0000, 0.0000},
        {-1.7500, 0.0000, 0.0000, 0.0000},
        {-2.0000, 0.0000, 0.0000, 0.0000},
        {-2.0000, 0.0000, 0.0000, 0.0000},
        {-2.0000, 0.0000, 0.0000, 0.0000},
        {-1.5000, 0.0000, 0.0000, 0.0000},
        {-1.5000, 0.0000, 0.0000, 0.0000},

        { 0.0000, 3.0000,-1.4000, 1.0000},
        { 0.0000, 3.1750,-1.3375, 1.0000},
        { 0.0000, 3.1750,-1.4375, 1.0000},
        { 0.0000, 3.0000,-1.5000, 1.0000},
        { 0.0000, 2.3000,-1.7500, 1.0000},
        { 0.0000, 1.6000,-2.0000, 1.0000},
        { 0.0000, 1.0000,-2.0000, 1.0000},
        { 0.0000, 0.4000,-2.0500, 1.0000},
        { 0.0000, 0.2000,-1.5000, 1.0000},
        { 0.0000, 0.0000,-1.5000, 1.0000},

        { 1.4000, 0.0000, 0.0000, 0.0000},
        { 1.3375, 0.0000, 0.0000, 0.0000},
        { 1.4375, 0.0000, 0.0000, 0.0000},
        { 1.5000, 0.0000, 0.0000, 0.0000},
        { 1.7500, 0.0000, 0.0000, 0.0000},
        { 2.0000, 0.0000, 0.0000, 0.0000},
        { 2.0000, 0.0000, 0.0000, 0.0000},
        { 2.0000, 0.0000, 0.0000, 0.0000},
        { 1.5000, 0.0000, 0.0000, 0.0000},
        { 1.5000, 0.0000, 0.0000, 0.0000},

        { 0.0000, 3.0000, 1.4000, 1.0000},
        { 0.0000, 3.1750, 1.3375, 1.0000},
        { 0.0000, 3.1750, 1.4375, 1.0000},
        { 0.0000, 3.0000, 1.5000, 1.0000},
        { 0.0000, 2.3000, 1.7500, 1.0000},
        { 0.0000, 1.6000, 2.0000, 1.0000},
        { 0.0000, 1.0000, 2.0000, 1.0000},
        { 0.0000, 0.4000, 2.0000, 1.0000},
        { 0.0000, 0.2000, 1.5000, 1.0000},
        { 0.0000, 0.0000, 1.5000, 1.0000},

    };
    NodePtr body = makeSurface(50, bodycps, 2, 3, 8, knots_circle,
                               14, knots14, 0.005, teapotmat);
    float handlecps[35][4] = {
        { 1.5000, 2.8000, 0.0000, 1.0000},
        { 2.5000, 2.8000, 0.0000, 1.0000},
        { 3.0000, 2.8000, 0.0000, 1.0000},
        { 3.0000, 2.2000, 0.0000, 1.0000},
        { 3.0000, 1.6000, 0.0000, 1.0000},
        { 2.6500, 1.0500, 0.0000, 1.0000},
        { 1.9000, 0.6000, 0.0000, 1.0000},

        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},
        { 0.0000, 0.0000, 0.3000, 0.0000},

        { 1.6000, 2.5000, 0.0000, 1.0000},
        { 2.3000, 2.5000, 0.0000, 1.0000},
        { 2.7000, 2.5000, 0.0000, 1.0000},
        { 2.7000, 2.2000, 0.0000, 1.0000},
        { 2.7000, 1.9000, 0.0000, 1.0000},
        { 2.5000, 1.5000, 0.0000, 1.0000},
        { 2.0000, 1.0000, 0.0000, 1.0000},

        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},
        { 0.0000, 0.0000,-0.3000, 0.0000},

        { 1.5000, 2.8000, 0.0000, 1.0000},
        { 2.5000, 2.8000, 0.0000, 1.0000},
        { 3.0000, 2.8000, 0.0000, 1.0000},
        { 3.0000, 2.2000, 0.0000, 1.0000},
        { 3.0000, 1.6000, 0.0000, 1.0000},
        { 2.6500, 1.0500, 0.0000, 1.0000},
        { 1.9000, 0.6000, 0.0000, 1.0000},
    };

    NodePtr handle = makeSurface(35, handlecps, 2, 3, 8, knots_circle,
                                 11, knots11, 0.005, teapotmat);
    float spoutcps[35][4] = {
        {-1.7000, 0.6000, 0.0000, 1.0000},
        {-3.1000, 0.9000, 0.0000, 1.0000},
        {-2.4000, 2.6000, 0.0000, 1.0000},
        {-3.3000, 3.0000, 0.0000, 1.0000},
        {-3.5250, 3.1250, 0.0000, 1.0000},
        {-3.4500, 3.1500, 0.0000, 1.0000},
        {-3.2000, 3.0000, 0.0000, 1.0000},

        { 0.0000, 0.0000, 0.6600, 0.0000},
        { 0.0000, 0.0000, 0.6600, 0.0000},
        { 0.0000, 0.0000, 0.2500, 0.0000},
        { 0.0000, 0.0000, 0.2500, 0.0000},
        { 0.0000, 0.0000, 0.2500, 0.0000},
        { 0.0000, 0.0000, 0.1500, 0.0000},
        { 0.0000, 0.0000, 0.1500, 0.0000},

        {-1.7000, 1.7000, 0.0000, 1.0000},
        {-2.6000, 1.7000, 0.0000, 1.0000},
        {-2.3000, 2.6000, 0.0000, 1.0000},
        {-2.7000, 3.0000, 0.0000, 1.0000},
        {-2.8000, 3.1000, 0.0000, 1.0000},
        {-2.9000, 3.1000, 0.0000, 1.0000},
        {-2.8000, 3.0000, 0.0000, 1.0000},

        { 0.0000, 0.0000,-0.6600, 0.0000},
        { 0.0000, 0.0000,-0.6600, 0.0000},
        { 0.0000, 0.0000,-0.2500, 0.0000},
        { 0.0000, 0.0000,-0.2500, 0.0000},
        { 0.0000, 0.0000,-0.2500, 0.0000},
        { 0.0000, 0.0000,-0.1500, 0.0000},
        { 0.0000, 0.0000,-0.1500, 0.0000},

        {-1.7000, 0.6000, 0.0000, 1.0000},
        {-3.1000, 0.9000, 0.0000, 1.0000},
        {-2.4000, 2.6000, 0.0000, 1.0000},
        {-3.3000, 3.0000, 0.0000, 1.0000},
        {-3.5250, 3.1250, 0.0000, 1.0000},
        {-3.4500, 3.1500, 0.0000, 1.0000},
        {-3.2000, 3.0000, 0.0000, 1.0000},
    };
    NodePtr spout = makeSurface(35, spoutcps, 2, 3, 8, knots_circle,
                                11, knots11, 0.005, teapotmat);

    beginEditCP(teapotroot);
    teapotroot->addChild(lid);
    teapotroot->addChild(body);
    teapotroot->addChild(handle);
    teapotroot->addChild(spout);
    endEditCP(teapotroot);
    return teapotroot;
}