コード例 #1
2
ファイル: testLabeling.cpp プロジェクト: chengzg/OSGAddOnsGV
OSG::NodeTransitPtr createLabeledTorus(OSG::Vec3f trans, int idx)
{
    OSG::NodeTransitPtr  node  = OSG::Node::create();
    OSG::TransformRefPtr xform = OSG::Transform::create();
    OSG::Matrix          mat;

    // --- setup transform ------------------
    mat.setIdentity();
    mat.setTranslate(trans);
    xform->setMatrix(mat);
    node->setCore(xform);


    // --- setup label ----------------------
    OSG::NodeRefPtr  labelNode = OSG::Node::create();
    OSG::LabelRefPtr label     = 
        (idx) ? createTextLabel(idx) : createIconLabel();

    updateLabelParams(label, idx);
    labelNode->setCore(label);

    // --- add torus ------------------------
    labelNode->addChild(OSG::makeTorus(.5, 2, 16, 16));

    node->addChild(labelNode);
    return node;
}
コード例 #2
0
ファイル: testLabeling.cpp プロジェクト: chengzg/OSGAddOnsGV
OSG::NodeTransitPtr createScene(void)
{
    // create the scene:
    OSG::TransformTransitPtr xform = OSG::Transform::create();

    OSG::Matrix mat;
    mat.setTranslate(OSG::Vec3f(2,0,0));
    xform->setMatrix(mat);

    OSG::NodeTransitPtr scene = OSG::Node::create();
    scene->addChild(createLabeledScene());
    scene->setCore(xform);

    OSG::commitChanges();

    return scene;
}
コード例 #3
0
ファイル: testLabeling.cpp プロジェクト: chengzg/OSGAddOnsGV
OSG::NodeTransitPtr createLabeledScene(void)
{
    OSG::NodeTransitPtr scene = OSG::Node::create();
    scene->setCore(OSG::Group::create());

#if 0
    scene->addChild(createLabeledTorus(OSG::Vec3f( 1, 3, 0), 0));
    scene->addChild(createLabeledTorus(OSG::Vec3f( 2, 3, 0), 0));
    scene->addChild(createLabeledTorus(OSG::Vec3f( 4, 3, 0), 0));
#endif
    scene->addChild(createLabeledTorus(OSG::Vec3f( 3, 3, 0), 0));
    scene->addChild(createLabeledTorus(OSG::Vec3f( 3,-3, 0), 1));
    scene->addChild(createLabeledTorus(OSG::Vec3f(-3, 3, 0), 2));
    scene->addChild(createLabeledTorus(OSG::Vec3f(-3,-3, 0), 3));

    return scene;
}
コード例 #4
0
OSG::NodeTransitPtr setupAnim(void)
{
    OSG::NodeTransitPtr returnValue = OSG::Node::create();

    returnValue->setCore(OSG::Group::create());

    static const OSG::Real32 aOffsets[6][3] = 
    {
        { -5.5,  0.0,  0.0 },
        {  5.5,  0.0,  0.0 },
        {  0.0, -5.5,  0.0 },
        {  0.0,  5.5,  0.0 },
        {  0.0,  0.0, -5.5 },
        {  0.0,  0.0,  5.5 }
    };

    static const OSG::Real32 aDiffuse[6][3] =
    {
        { 1.f, 0.f, 0.f },
        { 0.f, 1.f, 0.f },
        { 0.f, 0.f, 1.f },
        { 1.f, 1.f, 0.f },
        { 1.f, 0.f, 1.f },
        { 0.f, 1.f, 1.f }
    };

    for(OSG::UInt32 i = 0; i < 6; ++i)
    {
        OSG::NodeUnrecPtr pTN                = OSG::Node::create();
        
        pAnimTrs[i] = OSG::ComponentTransform::create();
        
        OSG::GeometryUnrecPtr pGeo     = OSG::makeBoxGeo(1.f, 1.f, 1.f, 
                                                         2,   2,   2);
        OSG::NodeUnrecPtr     pGeoNode = OSG::Node::create();
        
        pGeoNode->setCore(pGeo);

        OSG::SimpleMaterialUnrecPtr pMat = OSG::SimpleMaterial::create();
        
        pMat->setDiffuse(OSG::Color3f(aDiffuse[i][0],
                                      aDiffuse[i][1],
                                      aDiffuse[i][2]));
        pMat->setAmbient(OSG::Color3f(aDiffuse[i][0],
                                      aDiffuse[i][1],
                                      aDiffuse[i][2]));

        pGeo->setMaterial(pMat);

        pAnimTrs[i]->editTranslation().setValues(aOffsets[i][0],
                                                 aOffsets[i][1],
                                                 aOffsets[i][2]);
        
        pTN->setCore (pAnimTrs[i]);
        pTN->addChild(pGeoNode   );
        
        returnValue->addChild(pTN);
    }


    return returnValue;
}
コード例 #5
0
OSG::NodeTransitPtr makeScene( void )
{
    setupDefaultMaterial();

    // Let's create two untrimmed surfaces that lie beside each other.
    // Even if the tessellation error is set to be the same for
    // both surfaces, due to numerical instabilities and sampling errors
    // small one pixel gaps will appear. By reducing the error you can
    // make most gaps disappear, but there will be still some left, even
    // if you reduce the error to be extremely small -- and as a sideeffect
    // the tessellation time plus the triangle count will explode.
    // You can try this by supplying the '-nofb' switch and
    // reducing the error by the 'g' key during rendering.
    // Of course if you set different tessellation errors (generally the
    // case when using view-dependent LOD algorithms) the gaps
    // will be a lot more visible. Try the '-nofb' and '-de' switches, and
    // play around with different errors using the 'f' and 'g'
    // keys for the first surface, and the 'h' and 'j' keys for the
    // second surface.
    //
    // Note that this is not a very good example for the Fat Borders as
    // the surfaces are untrimmed, and they are also very nice numerically
    // (real world models are usually much worse) and a basic uniform
    // tessellation would probably get rid of the gaps (which are not very
    // visible in the first place due to the nice properties of these
    // surfaces). Note also that if you set too high errors or
    // radically different errors, the spike-through artifacts of the
    // Fat Borders will appear.
    // We will hopefully come up with a better example later. :-)

    OSG::NodeTransitPtr root  = OSG::Node::create();
    OSG::NodeRefPtr     surf1 = OSG::Node::create();
    OSG::NodeRefPtr     surf2 = OSG::Node::create();

    root->setCore( OSG::Group::create() );
    root->addChild( surf1 );
    root->addChild( surf2 );

    OSG::SurfaceRefPtr          surface1 = OSG::Surface         ::create();
    OSG::GeoPnt3fPropertyRefPtr cps1     = OSG::GeoPnt3fProperty::create();

    cps1->clear();
    cps1->push_back( OSG::Pnt3f(  1, -1,  0 ));
    cps1->push_back( OSG::Pnt3f(  1,  0,  0 ));
    cps1->push_back( OSG::Pnt3f(  1,  0,  1 ));
    cps1->push_back( OSG::Pnt3f(  1,  1,  1 ));

    cps1->push_back( OSG::Pnt3f(  0, -1,  0 ));
    cps1->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps1->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps1->push_back( OSG::Pnt3f(  0,  1,  1 ));

    cps1->push_back( OSG::Pnt3f(  0, -1,  1 ));
    cps1->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps1->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps1->push_back( OSG::Pnt3f(  0,  1,  0 ));

    cps1->push_back( OSG::Pnt3f( -1, -1,  1 ));
    cps1->push_back( OSG::Pnt3f( -1,  0,  1 ));
    cps1->push_back( OSG::Pnt3f( -1,  0,  0 ));
    cps1->push_back( OSG::Pnt3f( -1,  1,  0 ));

    OSG::SurfaceRefPtr          surface2 = OSG::Surface         ::create();
    OSG::GeoPnt3fPropertyRefPtr cps2     = OSG::GeoPnt3fProperty::create();

    cps2->clear();
    cps2->push_back( OSG::Pnt3f(  5, -2,  2 ));
    cps2->push_back( OSG::Pnt3f(  4, -1,  2 ));
    cps2->push_back( OSG::Pnt3f(  3,  0,  0 ));
    cps2->push_back( OSG::Pnt3f(  5,  1,  0 ));

    cps2->push_back( OSG::Pnt3f(  2, -1,  1 ));
    cps2->push_back( OSG::Pnt3f(  2,  0,  1 ));
    cps2->push_back( OSG::Pnt3f(  2,  0,  0 ));
    cps2->push_back( OSG::Pnt3f(  2,  1,  0 ));

    cps2->push_back( OSG::Pnt3f(  2, -1,  0 ));
    cps2->push_back( OSG::Pnt3f(  2,  0,  0 ));
    cps2->push_back( OSG::Pnt3f(  2,  0,  1 ));
    cps2->push_back( OSG::Pnt3f(  2,  1,  1 ));

    cps2->push_back( OSG::Pnt3f(  1, -1,  0 ));
    cps2->push_back( OSG::Pnt3f(  1,  0,  0 ));
    cps2->push_back( OSG::Pnt3f(  1,  0,  1 ));
    cps2->push_back( OSG::Pnt3f(  1,  1,  1 ));

    std::vector<OSG::Real64> knots1;
    std::vector<OSG::Pnt2f > points;
    knots1.clear();
    knots1.push_back(0);
    knots1.push_back(0);
    knots1.push_back(1);
    knots1.push_back(1);

    // first, let's clear the trimming
    surface1->removeCurves();

    // add simple outer trimming around the domain
    points.clear();
    points.push_back( OSG::Pnt2f(0,0) );
    points.push_back( OSG::Pnt2f(1,0) );
    surface1->addCurve( 1, knots1, points, true );
    points.clear();
    points.push_back( OSG::Pnt2f(1,0) );
    points.push_back( OSG::Pnt2f(1,1) );
    surface1->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(1,1) );
    points.push_back( OSG::Pnt2f(0,1) );
    surface1->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0,1) );
    points.push_back( OSG::Pnt2f(0,0) );
    surface1->addCurve( 1, knots1, points, false );

    // set up dimensions and knot vectors:
    surface1->setDimU( 3 );
    surface1->setDimV( 3 );
    surface1->editMFKnotsU()->clear();
    surface1->editMFKnotsU()->push_back( 0 );
    surface1->editMFKnotsU()->push_back( 0 );
    surface1->editMFKnotsU()->push_back( 0 );
    surface1->editMFKnotsU()->push_back( 0 );
    surface1->editMFKnotsU()->push_back( 1 );
    surface1->editMFKnotsU()->push_back( 1 );
    surface1->editMFKnotsU()->push_back( 1 );
    surface1->editMFKnotsU()->push_back( 1 );
    surface1->editMFKnotsV()->clear();
    surface1->editMFKnotsV()->push_back( 0 );
    surface1->editMFKnotsV()->push_back( 0 );
    surface1->editMFKnotsV()->push_back( 0 );
    surface1->editMFKnotsV()->push_back( 0 );
    surface1->editMFKnotsV()->push_back( 1 );
    surface1->editMFKnotsV()->push_back( 1 );
    surface1->editMFKnotsV()->push_back( 1 );
    surface1->editMFKnotsV()->push_back( 1 );

    // set control points
    surface1->setControlPoints( cps1 );

    // set error
    surface1->setError( g_error1 );

    // and finally set the material
    surface1->setMaterial( gpcl_defaultmat );

    // first, let's clear the trimming
    surface2->removeCurves();
    // add simple outer trimming around the domain
    points.clear();
    points.push_back( OSG::Pnt2f(1,0) );
    points.push_back( OSG::Pnt2f(2,0) );
    surface2->addCurve( 1, knots1, points, true );
    points.clear();
    points.push_back( OSG::Pnt2f(2,0) );
    points.push_back( OSG::Pnt2f(2,1) );
    surface2->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(2,1) );
    points.push_back( OSG::Pnt2f(1,1) );
    surface2->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(1,1) );
    points.push_back( OSG::Pnt2f(1,0) );
    surface2->addCurve( 1, knots1, points, false );

    // set up dimensions and knot vectors:
    surface2->setDimU( 3 );
    surface2->setDimV( 3 );
    surface2->editMFKnotsU()->clear();
    surface2->editMFKnotsU()->push_back( 1 );
    surface2->editMFKnotsU()->push_back( 1 );
    surface2->editMFKnotsU()->push_back( 1 );
    surface2->editMFKnotsU()->push_back( 1 );
    surface2->editMFKnotsU()->push_back( 2 );
    surface2->editMFKnotsU()->push_back( 2 );
    surface2->editMFKnotsU()->push_back( 2 );
    surface2->editMFKnotsU()->push_back( 2 );
    surface2->editMFKnotsV()->clear();
    surface2->editMFKnotsV()->push_back( 0 );
    surface2->editMFKnotsV()->push_back( 0 );
    surface2->editMFKnotsV()->push_back( 0 );
    surface2->editMFKnotsV()->push_back( 0 );
    surface2->editMFKnotsV()->push_back( 1 );
    surface2->editMFKnotsV()->push_back( 1 );
    surface2->editMFKnotsV()->push_back( 1 );
    surface2->editMFKnotsV()->push_back( 1 );

    // set control points
    surface2->setControlPoints( cps2 );

    // set error
    surface2->setError( g_error2 );

    // and finally set the material
    surface2->setMaterial( gpcl_defaultmat );

    surf1->setCore( surface1 );
    surf2->setCore( surface2 );

    gpcl_surface1 = surface1;
    gpcl_surface2 = surface2;

    return root;
}
コード例 #6
0
OSG::NodeTransitPtr makeScene( void )
{
    setupDefaultMaterial();

    OSG::NodeTransitPtr         root    = OSG::Node            ::create();
    OSG::SurfaceRefPtr          surface = OSG::Surface         ::create();
    OSG::GeoPnt3fPropertyRefPtr cps     = OSG::GeoPnt3fProperty::create();

    // control points should always be 3D for the time being,
    // rational support will be added later
    cps->clear();
    cps->push_back( OSG::Pnt3f(  1,  1,  2 ));
    cps->push_back( OSG::Pnt3f(  1,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  1,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  1, -1, -2 ));

    cps->push_back( OSG::Pnt3f(  0,  1,  0 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  0, -1,  1 ));

    cps->push_back( OSG::Pnt3f(  0,  1,  1 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  0, -1,  0 ));

    cps->push_back( OSG::Pnt3f( -1,  1,  1 ));
    cps->push_back( OSG::Pnt3f( -1,  0,  1 ));
    cps->push_back( OSG::Pnt3f( -1,  0,  0 ));
    cps->push_back( OSG::Pnt3f( -1, -1,  0 ));

    // let's clear the trimming
    surface->removeCurves();

    // set up dimensions and knot vectors:
    surface->setDimU( 3 );
    surface->setDimV( 3 );
    surface->editMFKnotsU()->clear();
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsV()->clear();
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    
    // set control points and texture control points
    surface->setControlPoints( cps );
    
    // set error
    surface->setError( g_error );
    
    // and finally set the material
    surface->setMaterial( gpcl_defaultmat );

    root->setCore( surface );

    gpcl_surface = surface;
    
    // Usually when the endEditCP() is called for an OSGSurface object
    // the need for (re)tessellation is flagged, and when the object
    // would be drawn on screen it gets tessellated. This might cause 
    // problems in a cluster environment as surfaces may get tessellated
    // more than once (e.g. on the server and on each client) which can
    // be _very_ slow and annoying.
    // 
    // The solution is "forcing" the tessellation by calling
    // OSGSurface::forceTessellate(). This will perform the tessellation
    // immediately, and setup flags so that automatic tessellation will
    // not be called again. This means that even if you change some or
    // all of the surface descriptiong FieldContainersin your OSGSurface
    // object it will _not_ be retessellated. You will have to "force"
    // tessellation again by calling OSGSurface::forceTessellate() whenever
    // you change something. See the calls in the keyboard() function
    // above.
    //
    // If you don't do clustering, you can probably just forget about all
    // this OSGSurface::forceTessellate() stuff (just like in the other 
    // Surface examples), it will just work automagically and tessellate 
    // your surface when needed (provided you don't forget the proper 
    // beginEditCP()/endEditCP() calls.
    if(useForceTesselate)
        gpcl_surface->forceTessellate();

    return root;
}
コード例 #7
0
OSG::NodeTransitPtr makeScene( void )
{
    setupDefaultMaterial();

    OSG::NodeTransitPtr         root    = OSG::Node            ::create();
    OSG::SurfaceRefPtr          surface = OSG::Surface         ::create();
    OSG::GeoPnt3fPropertyRefPtr cps     = OSG::GeoPnt3fProperty::create();

    // control points should always be 3D for the time being,
    // rational support will be added later
    cps->clear();
    cps->push_back( OSG::Pnt3f(  1,  1,  0 ));
    cps->push_back( OSG::Pnt3f(  1,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  1,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  1, -1,  1 ));

    cps->push_back( OSG::Pnt3f(  0,  1,  0 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  0, -1,  1 ));

    cps->push_back( OSG::Pnt3f(  0,  1,  1 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  1 ));
    cps->push_back( OSG::Pnt3f(  0,  0,  0 ));
    cps->push_back( OSG::Pnt3f(  0, -1,  0 ));

    cps->push_back( OSG::Pnt3f( -1,  1,  1 ));
    cps->push_back( OSG::Pnt3f( -1,  0,  1 ));
    cps->push_back( OSG::Pnt3f( -1,  0,  0 ));
    cps->push_back( OSG::Pnt3f( -1, -1,  0 ));
    
    std::vector<OSG::Real64> knots1;
    std::vector<OSG::Real64> knots2;
    std::vector<OSG::Pnt2f> points;
    knots1.clear();
    knots1.push_back(0);
    knots1.push_back(0);
    knots1.push_back(1);
    knots1.push_back(1);
    knots2.clear();
    knots2.push_back(0);
    knots2.push_back(0);
    knots2.push_back(0);
    knots2.push_back(1);
    knots2.push_back(1);
    knots2.push_back(1);
        
    // first, let's clear the trimming
    surface->removeCurves();

    // add the outer trimming around the domain
    points.clear();
    points.push_back( OSG::Pnt2f(0,0) );
    points.push_back( OSG::Pnt2f(1,0) );
    surface->addCurve( 1, knots1, points, true );
    points.clear();
    points.push_back( OSG::Pnt2f(1,0) );
    points.push_back( OSG::Pnt2f(1,1) );
    surface->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(1,1) );
    points.push_back( OSG::Pnt2f(0,1) );
    surface->addCurve( 1, knots1, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0,1) );
    points.push_back( OSG::Pnt2f(0,0) );
    surface->addCurve( 1, knots1, points, false );

    // add inner trimming loop 1
    points.clear();
    points.push_back( OSG::Pnt2f(0.3f,0.5f) );
    points.push_back( OSG::Pnt2f(0.1f,0.9f) );
    points.push_back( OSG::Pnt2f(0.5f,0.7f) );
    surface->addCurve( 2, knots2, points, true );
    points.clear();
    points.push_back( OSG::Pnt2f(0.5f,0.7f) );
    points.push_back( OSG::Pnt2f(0.9f,0.9f) );
    points.push_back( OSG::Pnt2f(0.7f,0.5f) );
    surface->addCurve( 2, knots2, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0.7f,0.5f) );
    points.push_back( OSG::Pnt2f(0.9f,0.1f) );
    points.push_back( OSG::Pnt2f(0.5f,0.3f) );
    surface->addCurve( 2, knots2, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0.5f,0.3f) );
    points.push_back( OSG::Pnt2f(0.1f,0.1f) );
    points.push_back( OSG::Pnt2f(0.3f,0.5f) );
    surface->addCurve( 2, knots2, points, false );
    
    // add inner trimming loop 2
    points.clear();
    points.push_back( OSG::Pnt2f(0.4f,0.5f) );
    points.push_back( OSG::Pnt2f(0.4f,0.4f) );
    points.push_back( OSG::Pnt2f(0.5f,0.4f) );
    surface->addCurve( 2, knots2, points, true );
    points.clear();
    points.push_back( OSG::Pnt2f(0.5f,0.4f) );
    points.push_back( OSG::Pnt2f(0.6f,0.4f) );
    points.push_back( OSG::Pnt2f(0.6f,0.5f) );
    surface->addCurve( 2, knots2, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0.6f,0.5f) );
    points.push_back( OSG::Pnt2f(0.6f,0.6f) );
    points.push_back( OSG::Pnt2f(0.5f,0.6f) );
    surface->addCurve( 2, knots2, points, false );
    points.clear();
    points.push_back( OSG::Pnt2f(0.5f,0.6f) );
    points.push_back( OSG::Pnt2f(0.4f,0.6f) );
    points.push_back( OSG::Pnt2f(0.4f,0.5f) );
    surface->addCurve( 2, knots2, points, false );
    
    // set up dimensions and knot vectors:
    surface->setDimU( 3 );
    surface->setDimV( 3 );
    surface->editMFKnotsU()->clear();
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 0 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsU()->push_back( 1 );
    surface->editMFKnotsV()->clear();
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 0 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    surface->editMFKnotsV()->push_back( 1 );
    
    // set control points and texture control points
    surface->setControlPoints( cps );
    
    // set error
    surface->setError( g_error );
    
    // and finally set the material
    surface->setMaterial( gpcl_defaultmat );

    root->setCore( surface );

    gpcl_surface = surface;

    return root;
}