NiSimpleRead.cpp - sample program

    <b>Source file:</b> Click the following link to view the source code file:
        - NiSimpleRead.cpp

    This section describes the SimpleRead sample program.

    @section sr_glb_dcl_blk Global Declaration Block
        The declaration block at the top of the program declares a Context object, a ScriptNode object, and an EnumerationErrors object. The context is workspace where the application builds an OpenNI production graph. The script node object loads and contains the OpenNI script and is the base node for the production graph. The <i>production graph</i> is a network of <i>production nodes</i> and is the principal OpenNI object model. The EnumerationErrors and XnStatus object types are for collecting errors from any of the OpenNI functions. Also declared is an OpenNI status flag for collecting return values from method calls.
        @code
            XnStatus nRetVal = XN_STATUS_OK;
            Context context;
            ScriptNode scriptNode;
            EnumerationErrors errors;
        @endcode

    @section sr_func_main Main Program

        @subsection sr_scrpt_sets_up_pg Use Script to Set up a Context and Production Graph

            The @ref xn::Context::InitFromXmlFile() "InitFromXmlFile()" method is a shorthand combination of two other initialization methods &mdash; @ref xn::Context::Init() "Init()" and then @ref xn::Context::RunXmlScriptFromFile() "RunXmlScriptFromFile()" &mdash; which initializes the context object and then creates a production graph from an XML file. The XML script file describes all the nodes you want to create. For each node description in the XML file, this method creates a node in the production graph.
            @code
                nRetVal = context.InitFromXmlFile(fn, scriptNode, &errors);
            @endcode

        @subsection sr_ver_nodes_in_script Verify Existence of Nodes in the Sample Script File

            Summary: This code is some more verification code. This time it checks that OpenNI found at least one node definition in the script file. The program continues execution only if at least one node definition if found.
            @code
            if (nRetVal == XN_STATUS_NO_NODE_PRESENT)
                {
                    XnChar strError[1024];
                    ...
                }
                else if (nRetVal != XN_STATUS_OK)
                {
                    printf("Open failed: %s\n", xnGetStatusString(nRetVal));
                    return (nRetVal);
                }
            }
            @endcode

        @subsection sr_get_node_from_pg Get a Node from the Production Graph

            Assuming that the above call to @ref xn::Context::InitFromXmlFile() "InitFromXmlFile()" succeeded, a production graph is then created.

            The @ref xn::Context::FindExistingNode() "FindExistingNode()" method in the following code block tries to get a reference to any one of the production nodes. This call specifies XN_NODE_TYPE_DEPTH to get a reference to a @ref xn::DepthGenerator "DepthGenerator" node. A DepthGenerator node generates a depth map as an array of pixels, where each pixel is a depth value representing a distance from the sensor in millimeters. A reference to the node is returned in the depth parameter.
            @code
                DepthGenerator depth = (DepthGenerator)context.findExistingNode(NodeType.DEPTH);
            @endcode

        @subsection sr_init_fps_calc Initialize the FPS Calculator

            The following declaration block initializes the FPS Calculator.
            @code
                XnFPSData xnFPS;
                nRetVal = xnFPSInit(&xnFPS, 180);
            @endcode

        @subsection sr_decl_dg_fo Declare the DepthGenerator's Frame Object

            The following statement declares a metadata object to provide a @ref glos_frame_object "frame object" for the @ref xn::DepthGenerator node. A @ref dict_gen_node "generator node's" @ref glos_frame_object "frame object" contains a generated data frame and all its associated properties. This frame object, comprising the data frame and its properties, is accessible through the node's metadata object.
            @code
                DepthMetaData depthMD;
            @endcode

        @subsection sr_main_prg_loop Main Program Loop

            The main program loop repeatedly updates the data available in the node for output, and then gets the frame object (via the metadata object). The program then calculates the mid-point of the scene's 2D (two-dimensional) area.

            @subsubsection sr_main_upd_data Updating the Data Available for Output

                the @ref xn::Context::WaitOneUpdateAll() "WaitOneUpdateAll()" method in the following statement updates all generator nodes in the context that have new data available, first waiting for a specified node to have new data available. The application can then get the data (for example, using a metadata GetData() method). This method has a timeout.
                @code
                    nRetVal = context.WaitOneUpdateAll(depth);
                @endcode

            @subsubsection sr_main_mark_the_frame  Mark the Frame
                @code
                    xnFPSMarkFrame(&xnFPS);
                @endcode

            @subsubsection sr_main_get_data Get the DepthGenerator's Data

                The following statement gets the latest generated depth @ref glos_frame_object "frame object", saving it as a metadata object.
                @code
                    depth.GetMetaData(depthMD);
                @endcode

                The following print statement accesses the frame data, its ID, and the frame data's associated configuration, The frame ID is the ID of the frame object. Frame IDs are a sequential unique number with a wrap around. This method is inherited from the OutputMetaData class.
                @code
                    printf("Frame %d Middle point is: %u. FPS: %f\n", depthMD.FrameID(), depthMD(depthMD.XRes() / 2, depthMD.YRes() / 2), xnFPSCalc(&xnFPS));
                @endcode

                In the above, @ref xn::MapMetaData::XRes() "XRes()" and @ref xn::MapMetaData::YRes() "YRes()" are the dimensions of the FOV in the scene. The call to <b>depthMD()</b> accesses a depth pixel through an X,Y coordinate. By calculating <b>XRes()/2</b> and <b>YRes()/2</b>, this accesses the middle pixel.