public Subdivide Build(BuildContext data)
            {
                switch (state)
                {
                case State.None:

                    Subdivide c = Initialize(data);

                    state = (c == null) ? State.Complete : State.Right;

                    return(c);

                case State.Right:

                    state = State.Finalize;

                    return(data.Get(isplit, imax));

                case State.Finalize:

                    int iescape = data.curNode - icur;

                    // Negative index means escape.
                    data.nodes[inode].i = -iescape;

                    state = State.Complete;

                    break;
                }

                return(null);
            }
            private Subdivide Initialize(BuildContext data)
            {
                int inum = imax - imin;

                icur = data.curNode;

                ChunkyTriMeshNode[] nodes = data.nodes;
                BoundsItem[]        items = data.items;

                if (data.curNode > nodes.Length)
                {
                    return(null);
                }

                inode = data.curNode++;

                if (inum <= data.trisPerChunk)
                {
                    // Leaf
                    DeriveExtents(items
                                  , imin
                                  , imax
                                  , ref nodes[inode]);

                    // Copy triangles.
                    nodes[inode].i     = data.curTri;
                    nodes[inode].count = inum;

                    for (int i = imin; i < imax; ++i)
                    {
                        int pi = items[i].i * 3;
                        int pd = data.curTri * 3;

                        data.tris[pd + 0] = data.inTris[pi + 0];
                        data.tris[pd + 1] = data.inTris[pi + 1];
                        data.tris[pd + 2] = data.inTris[pi + 2];

                        data.areas[data.curTri] = data.inAreas[items[i].i];

                        data.curTri++;
                    }
                }
                else
                {
                    // Split
                    DeriveExtents(items, imin, imax, ref nodes[inode]);

                    int axis =
                        (nodes[inode].zmax - nodes[inode].zmin
                         > nodes[inode].xmax - nodes[inode].xmin)
                            ? 1 : 0;

                    if (axis == 0)
                    {
                        // Sort along x-axis
                        Array.Sort <BoundsItem>(items, imin, inum, mCompareX);
                    }
                    else if (axis == 1)
                    {
                        // Sort along y-axis
                        Array.Sort <BoundsItem>(items, imin, inum, mCompareZ);
                    }

                    isplit = imin + inum / 2;

                    // Left
                    return(data.Get(imin, isplit));
                }

                return(null);
            }