//	Push draw data
 public void PushDrawData(DRAWDATA data)
 {
     drawDataList.Add(data);
 }
        void CollectRenderNodes_r(int nodeIndex)
        {
            QtreeNode node = nodeBuf[nodeIndex];

            //	Only render node whose info is up-to-date
            if (node.updateCnt != updateCnt)
            {
                //	If a node isn't up-to-date, all it's children must not be.
                return;
            }

            //	do camera cull with node's AABB at first, but node may not have min-y and max-y
            //	at this moment if it's mesh wasn't built, so now we only do a conservative check
            //	with x and z axis.
            //	NOTE: we ONLY consider tranlation of terrain, but not rotation and scale
            Vector3 offset  = terrain.transform.position;
            Rect    rcLocal = node.CalcLocalArea(terrain.gridSize);
            Vector3 mins    = new Vector3(rcLocal.xMin + offset.x, -10000.0f, rcLocal.yMin + offset.z);
            Vector3 maxs    = new Vector3(rcLocal.xMax + offset.x, 10000.0f, rcLocal.yMax + offset.z);
            Bounds  aabb    = new Bounds();

            aabb.SetMinMax(mins, maxs);

            if (!GeometryUtility.TestPlanesAABB(camPlanes, aabb))
            {
                return;                    //	The whole node isn't visible
            }
            if (node.meshState == (byte)eNodeMeshState.LOAD_INBORN ||
                node.meshState == (byte)eNodeMeshState.LOD_GRADEUP)
            {
                //	Get index buffer according to neighbour's LOD grade
                int sideMask = 0;
                for (int i = 0; i < 4; i++)
                {
                    if (node.neighbour[i] < 0)
                    {
                        continue;
                    }

                    QtreeNode neighbour = nodeBuf[node.neighbour[i]];
                    if (neighbour.updateCnt == updateCnt && neighbour.areaLOD > node.areaLOD)
                    {
                        sideMask |= (1 << i);
                    }
                }

                //	This node's may be drawn
                ComputeBuffer _vertCB  = null;
                ComputeBuffer _indexCB = null;
                QuadtreeMesh  nodeMesh = null;

                if (node.meshState == (byte)eNodeMeshState.LOAD_INBORN)
                {
                    nodeMesh = terrain.meshMan.GetNodeMesh(nodeIndex);
                    if (nodeMesh != null)
                    {
                        _vertCB  = nodeMesh.vertCB;
                        _indexCB = terrain.trnRes.GetNodeIndexCB(sideMask, -1);
                    }
                }
                else if (node.meshState == (byte)eNodeMeshState.LOD_GRADEUP)
                {
                    //	LOD grade-up rendering, use parent's mesh
                    Debug.Assert(node.parent >= 0);
                    nodeMesh = terrain.meshMan.GetNodeMesh(node.parent);
                    if (nodeMesh != null)
                    {
                        _vertCB  = nodeMesh.vertCB;
                        _indexCB = terrain.trnRes.GetNodeIndexCB(sideMask, node.childPos);
                    }
                }

                if (_vertCB != null && _indexCB != null)
                {
                    //	do camera cull again with more precise aabb
                    mins.y = nodeMesh.aabb.min.y + offset.y;
                    maxs.y = nodeMesh.aabb.max.y + offset.y;
                    aabb.SetMinMax(mins, maxs);
                    if (!GeometryUtility.TestPlanesAABB(camPlanes, aabb))
                    {
                        return;                            // The whole node isn't visible
                    }
                    //	Push node to rendering collector
                    DRAWDATA drawData = new DRAWDATA()
                    {
                        node     = node,
                        nodeAABB = aabb,
                        vertCB   = _vertCB,
                        indexCB  = _indexCB,
                    };

                    curRenderer.PushDrawData(drawData);
                }
            }

            if (!node.IsLeaf())
            {
                //	Go on for children
                for (int i = 0; i < 4; i++)
                {
                    CollectRenderNodes_r(node.children[i]);
                }
            }
        }