public void generateNeighborLinks(OpenHeightfield field)
        {
            if( field == null )
            {
                Logger.LogError("[OpenHeightfieldBuilder][generateNeighborLinks]field Empty"); 
                return; 
            }

            OpenHeightfield.OpenHeightFieldIterator iter = field.GetEnumerator(); 
            while( iter.MoveNext() )
            {
                OpenHeightSpan span = iter.Current; 
                for(int dir = 0; dir < 4; ++dir)
                {
                    //邻居的GirdIndex
                    int nWidthIndex = (iter.widthIndex() + BoundeField.getDirOffsetWidth(dir));
                    int nDepthIndex = (iter.depthIndex() + BoundeField.getDirOffsetDepth(dir)); 
                    
                    for(OpenHeightSpan nSpan = field.getData(nWidthIndex,nDepthIndex);
                        nSpan != null;
                        nSpan = nSpan.next())
                    {
                        int maxFloor = Math.Max(span.floor(), nSpan.floor());
                        int minCeling = Math.Min(span.ceiling(), nSpan.ceiling()); 

                        
                        if( (minCeling - maxFloor) >= mMinTraversableHeight   //邻居之间的通道足够高,可以通过 
                            && Math.Abs(nSpan.floor() - span.floor()) <= mMaxTraversableStep )  //两邻居之间的落差足够小
                        {
                            span.setNeighbor(dir, nSpan);
                            break; 
                        }
                    }

                }
            }
        }
            public bool MoveNext()
            {
                if (mOpenHeightfield == null)
                {
                    Logger.LogError("[OpenHeightfield][OpenHeightFieldIterator][MoveNext]Null");
                    return(false);
                }

                //公有逻辑
                if (mNext != null)
                {
                    if (mNext.next() != null)
                    {
                        mNext = mNext.next();
                        return(true);
                    }
                    else
                    {
                        if (mIsReverseIter)
                        {
                            mNextWidth--;
                        }
                        else
                        {
                            mNextWidth++;
                        }
                    }
                }

                if (mIsReverseIter)
                {
                    #region 反向遍历
                    for (int depthIndex = mNextDepth; depthIndex >= 0; --depthIndex)
                    {
                        for (int widthIndex = mNextWidth; widthIndex >= 0; --widthIndex)
                        {
                            OpenHeightSpan span = mOpenHeightfield.getData(widthIndex, depthIndex);
                            if (span != null)
                            {
                                mNext      = span;
                                mNextWidth = widthIndex;
                                mNextDepth = depthIndex;
                                return(true);
                            }
                        }
                        mNextWidth = 0;
                    }

                    mNext      = null;
                    mNextDepth = -1;
                    mNextWidth = -1;

                    return(false);

                    #endregion
                }
                else
                {
                    #region 正向遍历
                    for (int depthIndex = mNextDepth; depthIndex < mOpenHeightfield.depth(); ++depthIndex)
                    {
                        for (int widthIndex = mNextWidth; widthIndex < mOpenHeightfield.width(); widthIndex++)
                        {
                            OpenHeightSpan span = mOpenHeightfield.getData(widthIndex, depthIndex);
                            if (span != null)
                            {
                                mNext      = span;
                                mNextWidth = widthIndex;
                                mNextDepth = depthIndex;
                                return(true);
                            }
                        }
                        mNextWidth = 0;
                    }

                    mNext      = null;
                    mNextDepth = -1;
                    mNextWidth = -1;

                    return(false);

                    #endregion
                } // if-else
            }     // MoveNext
Exemplo n.º 3
0
        public void apply(OpenHeightfield field)
        {
            if (null == field)
            {
                Logger.LogError("[FilterOutSmallRegions][apply]field null");
                return;
            }

            if (field.regionCount() < 2)
            {
                Logger.LogError("[FilterOutSmallRegions][apply]RegionCnt|{0}", field.regionCount());
                return;
            }

            //PS:索引即是对应的ID
            Region[] regions = new Region[field.regionCount()];
            for (int i = 0; i < field.regionCount(); ++i)
            {
                regions[i] = new Region(i);
            }

            #region 收集邻接信息
            OpenHeightfield.OpenHeightFieldIterator iter = field.GetEnumerator();
            while (iter.MoveNext())
            {
                OpenHeightSpan span = iter.Current;
                if (span.regionID() <= NULL_REGION)
                {
                    continue;
                }

                //索引即RegionID
                Region region = regions[span.regionID()];
                region.spanCount++;

                for (OpenHeightSpan nextHigherSpan = span.next();
                     nextHigherSpan != null;
                     nextHigherSpan = nextHigherSpan.next()
                     )
                {
                    int nextHigherSpanRegionID = nextHigherSpan.regionID();
                    if (nextHigherSpanRegionID <= NULL_REGION)
                    {
                        continue;
                    }
                    //因为是同属一个Grid的,所以肯定是重叠的
                    if (!region.overlappingRegions.Contains(nextHigherSpanRegionID))
                    {
                        region.overlappingRegions.Add(nextHigherSpanRegionID);
                    }
                } //for

                if (region.connections.Count > 0)
                {
                    continue;
                }

                int edgeDirection = getRegionEdgeDirection(span);
                if (edgeDirection != -1)
                {
                    findRegionConnections(span, edgeDirection, ref region.connections);
                }
            } // while

            #endregion

            #region 清理孤岛Region
            for (int regionID = 1; regionID < field.regionCount(); ++regionID)
            {
                Region region = regions[regionID];
                if (0 == region.spanCount)
                {
                    continue;
                }

                // 有且仅有一个 Null Region 邻居
                if (region.connections.Count == 1 &&
                    region.connections[0] == NULL_REGION)
                {
                    if (region.spanCount < mMinUnconnectedRegionSize)
                    {
                        region.resetWithID(0);
                    }
                }
            }  //for

            #endregion

            #region 合并小的Region
            int mergeCount;
            do
            {
                mergeCount = 0;

                foreach (Region region in regions)
                {
                    if (region.id <= NULL_REGION ||
                        region.spanCount == 0)
                    {
                        continue;
                    }

                    if (region.spanCount > mMergeRegionSize)
                    {
                        continue;
                    }

                    Region targetMergeRegion = null;
                    int    smallestSizeFound = int.MaxValue;

                    foreach (int nRegionID in region.connections)
                    {
                        if (nRegionID <= 0)
                        {
                            continue;
                        }

                        Region nRegion = regions[nRegionID];
                        if (nRegion.spanCount < smallestSizeFound &&
                            canMerge(region, nRegion))
                        {
                            targetMergeRegion = nRegion;
                            smallestSizeFound = nRegion.spanCount;
                        }
                    } // foreach nRegionID

                    if (targetMergeRegion != null &&
                        mergeRegions(targetMergeRegion, region))     //为啥是反过来Merge。。。
                    {
                        int oldRegionID = region.id;
                        region.resetWithID(targetMergeRegion.id);

                        foreach (Region r in regions)
                        {
                            if (r.id <= NULL_REGION)
                            {
                                continue;
                            }
                            if (r.id == oldRegionID)
                            {
                                r.id = targetMergeRegion.id;
                            }
                            else
                            {
                                replaceNeighborRegionID(r, oldRegionID, targetMergeRegion.id);
                            }
                        } // foreach regions

                        mergeCount++;
                    } // if mergerRegion
                }     // foreach region
            } while (mergeCount > 0);

            #endregion

            #region  re-map 区域ID,保持ID连接
            foreach (Region region in regions)
            {
                if (region.id >= NULL_REGION)
                {
                    region.remap = true;
                }
            }

            int currRegionID = NULL_REGION;
            foreach (Region region in regions)
            {
                if (!region.remap)
                {
                    continue;
                }
                currRegionID++;
                int oldID = region.id;

                foreach (Region r in regions)
                {
                    if (r.id == oldID)
                    {
                        r.id    = currRegionID;
                        r.remap = false;
                    }
                } //foreach
            }     //foreach

            field.setRegionCount(currRegionID + 1);

            iter.Reset();
            while (iter.MoveNext())
            {
                OpenHeightSpan span = iter.Current;
                if (NULL_REGION == span.regionID())
                {
                    continue;
                }
                else
                {
                    //真正re-map一下
                    span.setRegionID(regions[span.regionID()].id);
                }
            }

            #endregion
        }  //apply