# far_tutorial_4_3.cpp

https://github.com/PixarAnimationStudios/OpenSubdiv/blob/release/tutorials/far/tutorial_4_3/far_tutorial_4_3.cpp

System Message: WARNING/2 (`/build/opensubdiv/src/OpenSubdiv-3_6_1/build/documentation/far_tutorial_4_3.rst`, line 9)

Cannot analyze code. Pygments package not found.

    .. code:: c++

        //------------------------------------------------------------------------------
        // Tutorial description:
        //
        // This tutorial shows how to create and manipulate table of cascading stencils.
        //
        // We initialize a Far::TopologyRefiner with a cube and apply uniform
        // refinement. We then use a Far::StencilTableFactory to generate a stencil
        // table. We set the factory Options to not factorize intermediate levels,
        // thus giving a table of "cascading" stencils.
        //
        // We then apply the stencils to the vertex position primvar data, and insert
        // a hierarchical edit at level 1. This edit is smoothed by the application
        // of the subsequent stencil cascades.
        //
        // The results are dumped into an OBJ file that shows the intermediate levels
        // of refinement of the original cube.
        //

        #include <opensubdiv/far/topologyDescriptor.h>
        #include <opensubdiv/far/stencilTable.h>
        #include <opensubdiv/far/stencilTableFactory.h>

        #include <cstdio>
        #include <cstring>

        //------------------------------------------------------------------------------
        // Vertex container implementation.
        //
        struct Vertex {

            // Minimal required interface ----------------------
            Vertex() { }

            Vertex(Vertex const & src) {
                _position[0] = src._position[0];
                _position[1] = src._position[1];
                _position[2] = src._position[2];
            }

            void Clear( void * =0 ) {
                _position[0]=_position[1]=_position[2]=0.0f;
            }

            void AddWithWeight(Vertex const & src, float weight) {
                _position[0]+=weight*src._position[0];
                _position[1]+=weight*src._position[1];
                _position[2]+=weight*src._position[2];
            }

            // Public interface ------------------------------------
            void SetPosition(float x, float y, float z) {
                _position[0]=x;
                _position[1]=y;
                _position[2]=z;
            }

            float const * GetPosition() const {
                return _position;
            }

            float * GetPosition() {
                return _position;
            }

        private:
            float _position[3];
        };

        //------------------------------------------------------------------------------
        // Cube geometry from catmark_cube.h

        static float g_verts[24] = {-0.5f, -0.5f,  0.5f,
                                     0.5f, -0.5f,  0.5f,
                                    -0.5f,  0.5f,  0.5f,
                                     0.5f,  0.5f,  0.5f,
                                    -0.5f,  0.5f, -0.5f,
                                     0.5f,  0.5f, -0.5f,
                                    -0.5f, -0.5f, -0.5f,
                                     0.5f, -0.5f, -0.5f };

        static int g_nverts = 8,
                   g_nfaces = 6;

        static int g_vertsperface[6] = { 4, 4, 4, 4, 4, 4 };

        static int g_vertIndices[24] = { 0, 1, 3, 2,
                                         2, 3, 5, 4,
                                         4, 5, 7, 6,
                                         6, 7, 1, 0,
                                         1, 7, 5, 3,
                                         6, 0, 2, 4  };

        using namespace OpenSubdiv;

        static Far::TopologyRefiner * createTopologyRefiner();

        //------------------------------------------------------------------------------
        int main(int, char **) {

            // Generate a Far::TopologyRefiner (see tutorial_1_1 for details).
            Far::TopologyRefiner * refiner = createTopologyRefiner();

            // Uniformly refine the topology up to 'maxlevel'.
            int maxlevel = 4;
            refiner->RefineUniform(Far::TopologyRefiner::UniformOptions(maxlevel));

            // Use the Far::StencilTable factory to create cascading stencil table
            // note: we want stencils for each refinement level
            //       "cascade" mode is achieved by setting "factorizeIntermediateLevels"
            //       to false
            Far::StencilTableFactory::Options options;
            options.generateIntermediateLevels=true;
            options.factorizeIntermediateLevels=false;
            options.generateOffsets=true;

            Far::StencilTable const * stencilTable =
                Far::StencilTableFactory::Create(*refiner, options);

            std::vector<Vertex> vertexBuffer(refiner->GetNumVerticesTotal()-g_nverts);

            Vertex * destVerts = &vertexBuffer[0];

            int start = 0, end = 0; // stencil batches for each level of subdivision
            for (int level=0; level<maxlevel; ++level) {

                int nverts = refiner->GetLevel(level+1).GetNumVertices();

                Vertex const * srcVerts = reinterpret_cast<Vertex *>(g_verts);
                if (level>0) {
                     srcVerts = &vertexBuffer[start];
                }

                start = end;
                end += nverts;

                stencilTable->UpdateValues(srcVerts, destVerts, start, end);

                // apply 2 hierarchical edits on level 1 vertices
                if (level==1) {
                    float * pos = destVerts[start+5].GetPosition();
                    pos[1] += 0.5f;

                    pos = destVerts[start+20].GetPosition();
                    pos[0] += 0.25f;
                }
            }

            { // Output OBJ of the highest level refined -----------

                Vertex * verts = &vertexBuffer[0];

                // Print vertex positions
                for (int level=1, firstvert=0; level<=maxlevel; ++level) {

                    Far::TopologyLevel const & refLevel = refiner->GetLevel(level);

                    printf("g level_%d\n", level);

                    int nverts = refLevel.GetNumVertices();
                    for (int vert=0; vert<nverts; ++vert) {
                        float const * pos = verts[vert].GetPosition();
                        printf("v %f %f %f\n", pos[0], pos[1], pos[2]);
                    }
                    verts += nverts;

                    // Print faces
                    for (int face=0; face<refLevel.GetNumFaces(); ++face) {

                        Far::ConstIndexArray fverts = refLevel.GetFaceVertices(face);

                        // all refined Catmark faces should be quads
                        assert(fverts.size()==4);

                        printf("f ");
                        for (int vert=0; vert<fverts.size(); ++vert) {
                            printf("%d ", fverts[vert]+firstvert+1); // OBJ uses 1-based arrays...
                        }
                        printf("\n");
                    }
                    firstvert+=nverts;
                }
            }

            delete refiner;
            delete stencilTable;
            return EXIT_SUCCESS;
        }

        //------------------------------------------------------------------------------
        static Far::TopologyRefiner *
        createTopologyRefiner() {

            // Populate a topology descriptor with our raw data.
            typedef Far::TopologyDescriptor Descriptor;

            Sdc::SchemeType type = OpenSubdiv::Sdc::SCHEME_CATMARK;

            Sdc::Options options;
            options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);

            Descriptor desc;
            desc.numVertices = g_nverts;
            desc.numFaces = g_nfaces;
            desc.numVertsPerFace = g_vertsperface;
            desc.vertIndicesPerFace = g_vertIndices;

            // Instantiate a Far::TopologyRefiner from the descriptor.
            return Far::TopologyRefinerFactory<Descriptor>::Create(desc,
                    Far::TopologyRefinerFactory<Descriptor>::Options(type, options));

        }

        //------------------------------------------------------------------------------

- User Docs
- API Docs
- Release Notes
- Forum

TM & © 1986 - 2017 PIXAR. ALL RIGHTS RESERVED. Terms of Use