} // public bool setNaviPortal_forShortestWay(int iSeqCell)

    // Collect all blocks requestcell to goal. And then buildup shortest way start to goal.
    // 요청셀 부터 골까지의 길 셀만을 모은다(가장 짧은 길을 택한다)
    public void collectWayToGoalLinear(int iCellStart,
                                       ref List <CNAVICELL> listSequenceCell_)
    {
        if (m_arrNavicells.Length <= iCellStart || 0 > iCellStart)
        {
            return;
        }

        bool      bCollectComplete = false;
        CNAVICELL cellWay          = m_arrNavicells[iCellStart];

        bCollectComplete = false;
        listSequenceCell_.Add(cellWay);     // collect start cell first.

        //@ first collect all blocks start -> goal.
        while (false == bCollectComplete)
        {
            int iIdxCellBestWay = cellWay.getIdxCell_nextWay();

            if (CNAVICELL.NULL_CELL == iIdxCellBestWay)
            {
                return;
            }

            cellWay = m_arrNavicells[iIdxCellBestWay];

            listSequenceCell_.Add(cellWay); // Last unit must be goalcell.

            if (true == cellWay.IsGoalCell())
            {
                bCollectComplete = true;
            }
        } // while (false == bCollectComplete)
    }     // public void collectWayToGoalLinear
Beispiel #2
0
    public void setLinkAllAdjs(ref CNAVICELL[] arrnavicellall, ref List <int> listCellAdjCollected)
    {
        bool bComputeOK           = false;
        int  iLevelFromGoalParent = m_iLevelToGoal;
        int  iLevelBlockroad      = m_iLevelBlockroadToGoal;

        CNAVICELL.E_CELL_SIDEEDGE eEdgeAdj;

        for (int iEdge = 0; iEdge < 3; ++iEdge)
        {
            eEdgeAdj = (CNAVICELL.E_CELL_SIDEEDGE)iEdge;
            int iSeqCellAdj = m_arriAdjCells[iEdge];
            if (CNAVICELL.NULL_CELL == iSeqCellAdj)
            {
                continue;
            }
            if (eEdgeAdj == m_eEdge_bestway)
            {
                continue;
            }

            CNAVICELL naviCellAdj = arrnavicellall[iSeqCellAdj];

            bComputeOK = naviCellAdj.setLinkcomputeCell(iLevelFromGoalParent + 1,
                                                        m_iSeqCell,
                                                        m_arrfcosttoGoal_edge[iEdge],
                                                        iLevelBlockroad);

            if (true == bComputeOK)
            {
                listCellAdjCollected.Add(iSeqCellAdj);
            }
        } // for( int iEdge=0; iEdge<3; ++iEdge)
    }
    // 함수:Mapping Navigation()
    // Build up cost of the way from the goal iterating all cells.
    // 1. Calculate cost of the way from the goal which iterating all cells.
    // -return:Updated Cells
    protected void mappingNavigation_(List <int> listCellsGoal, List <int> listCellsBlock, List <int> listCellsBlockroad, ref CNAVICELL[] arrNavicells)
    {
        bool       bMappingComplete = false;
        int        iLevelFromGoalRefer = 0, iLevelFromGoalIterator = 0;
        List <int> listCellAdjCollected = new List <int>();
        List <int> listCellsIterator_   = new List <int>();

        //@ Set all block cell
        for (int iSeqCell = 0; iSeqCell < listCellsBlock.Count; ++iSeqCell)
        {
            CNAVICELL naviCellCurr = m_arrNavicells[listCellsBlock[iSeqCell]];
            naviCellCurr.SetBlockCell();
        }

        //@ Set all blockroad cell
        for (int iSeqCell = 0; iSeqCell < listCellsBlockroad.Count; ++iSeqCell)
        {
            CNAVICELL naviCellCurr = m_arrNavicells[listCellsBlockroad[iSeqCell]];
            naviCellCurr.SetBlockRoadCell();
        }

        //@ construct top(GOAL) to leap
        for (int iSeqCellGoal = 0; iSeqCellGoal < listCellsGoal.Count; ++iSeqCellGoal)
        {
            int       iSeqCell     = listCellsGoal[iSeqCellGoal];
            CNAVICELL naviCellCurr = arrNavicells[iSeqCell];
            naviCellCurr.setLinkcomputeNaviCell_GOAL(0, (int)(CNAVICELL.E_CELL_STATUS.CELL_STATUS_GOAL), 0.0f);
            listCellsIterator_.Add(iSeqCell);
        }

        //@ Simulate validation or not.
        do      // while( false==bMappingComplete )
        {
            foreach (int iSeqCellParent_ in listCellsIterator_)
            {
                CNAVICELL naviCellParent = arrNavicells[iSeqCellParent_];
                naviCellParent.setLinkAllAdjs(ref m_arrNavicells, ref listCellAdjCollected);
            }

            if (listCellAdjCollected.Count < 1)
            {
                bMappingComplete = true;
                break;
            }

            iLevelFromGoalRefer = ++iLevelFromGoalIterator;

            listCellsIterator_.Clear();
            listCellAdjCollected.Sort();

            foreach (int iSeqCellADJ in listCellAdjCollected)
            {
                listCellsIterator_.Add(iSeqCellADJ);
            }
            listCellAdjCollected.Clear();
        } while (false == bMappingComplete);

        m_iDepthLevel_Navi = iLevelFromGoalRefer;
    } // protected void mappingNavigation_(List<int> listCellsGoal, List<int> listCellsBlock, ref CNAVICELL[] arrNavicells)
    protected int simulateMappingNavigation_(List <int> listCellsGoal, List <int> listCellsBlock, ref CNAVICELL[] arrNavicells)
    {
        int        iLevelFromGoalRefer = -1, iIteratorLevel = 0;
        List <int> listCellsCurrentLevel = new List <int>();

        for (int iSeqCell = 0; iSeqCell < listCellsBlock.Count; ++iSeqCell)
        {
            CNAVICELL naviCellCurr = arrNavicells[listCellsBlock[iSeqCell]];
            naviCellCurr.SetBlockCell();
        }

        //@ Set all Goal, block cell
        for (int iSeqCellGoal = 0; iSeqCellGoal < listCellsGoal.Count; ++iSeqCellGoal)
        {
            int       iSeqCell     = listCellsGoal[iSeqCellGoal];
            CNAVICELL naviCellCurr = arrNavicells[iSeqCell];
            naviCellCurr.setLinkcomputeSimulate(0, (int)(CNAVICELL.E_CELL_STATUS.CELL_STATUS_GOAL));
            listCellsCurrentLevel.Add(iSeqCell);
        }
        listCellsCurrentLevel.Sort();

        List <int> listCellsNextLevel = new List <int>();
        bool       bMappingComplete   = false;

        while (false == bMappingComplete)
        {
            foreach (int iSeqCell in listCellsCurrentLevel)
            {
                CNAVICELL naviCellParent = arrNavicells[iSeqCell];
                naviCellParent.setLinkAllAdjs_simulate(iSeqCell,
                                                       iLevelFromGoalRefer,
                                                       ref m_arrNavicells,
                                                       ref listCellsCurrentLevel,
                                                       ref listCellsNextLevel);
            }

            if (listCellsNextLevel.Count > 0)
            {
                iLevelFromGoalRefer = iIteratorLevel++;
                listCellsNextLevel.Sort();

                listCellsCurrentLevel.Clear();

                foreach (int iSeqCellAdjacentNextlevel in listCellsNextLevel)
                {
                    listCellsCurrentLevel.Add(iSeqCellAdjacentNextlevel);
                }
                listCellsNextLevel.Clear();
            }
            else
            {
                bMappingComplete = true;
                break;
            }
        } // while (false == bMappingComplete)

        return(iLevelFromGoalRefer);
    } // protected bool mappingNavigation_Simulate_(List<int> listCellsGoal, List<int> listCellsBlock, ref CNAVICELL[] arrNavicells)
    } // public bool getPosWayToGoal(int iSeqCell_current, ref CCellWayto pntNavi_out)

    //@ -Return:pre-calculated shortest cost middle edge position (way to goal) (when mappingnavigation).
    //  Every navicell have just only one shortest way to GOAL.
    public CNAVICELL.E_CELL_STATUS getPosNextWayTo(int iSeqCell_current, ref CCellWayto pntNavi_out)
    {
        if (iSeqCell_current > (int)m_arrNavicells.Length || iSeqCell_current < 0)
        {
            Debug.Log("!!!ERROR iSeqCell_current>(int)m_arrNavicells.size()||iSeqCell_current<0");

            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_NULL);
        }

        CNAVICELL naviCellcurr = m_arrNavicells[iSeqCell_current];
        Vector3   v3PosDest    = new Vector3();
        Vector3   v3PosStart   = new Vector3();

        naviCellcurr.getPos_nextWay(ref v3PosStart);

        int iIdxCellCurrent = naviCellcurr.seqCell;
        int iIdxCellNextTo  = naviCellcurr.getIdxCell_nextWay();

        if (CNAVICELL.NULL_CELL == iIdxCellNextTo)
        {
            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_NULL);
        }

        CNAVICELL naviCellNext = m_arrNavicells[iIdxCellNextTo];

        if (naviCellNext.IsGoalCell())
        {
            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_GOAL);
        }

        bool bGetPos_nextWay = naviCellNext.getPos_nextWay(ref v3PosDest);

        if (false == bGetPos_nextWay)
        {
            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_NULL);
        }

        Vector3 posEdgeTo0 = new Vector3(), posEdgeTo1 = new Vector3(), posEdgeFrom0 = new Vector3(), posEdgeFrom1 = new Vector3();

        naviCellcurr.getPntsOfEdgeBestway(ref posEdgeFrom0, ref posEdgeFrom1);
        naviCellNext.getPntsOfEdgeBestway(ref posEdgeTo0, ref posEdgeTo1);
        Vector3 v3dirEntryToNextway = naviCellNext.getDirEntryToGoal(iIdxCellCurrent);

        pntNavi_out.setPntnavi(iIdxCellNextTo,
                               naviCellcurr.leveltogoal,
                               v3PosStart,
                               v3PosDest,
                               posEdgeFrom0,
                               posEdgeFrom1,
                               posEdgeTo0,
                               posEdgeTo1,
                               naviCellNext.getPos_cellCenter(),
                               v3dirEntryToNextway);

        return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_ROAD);
    } // public bool getPosWayToGoal(int iSeqCell_current, ref CCellWayto pntNavi_out)
    public bool getCell(uint iIdxCell, ref CNAVICELL naviCell)
    {
        if (iIdxCell > m_arrNavicells.Length)
        {
            return(false);
        }

        naviCell = m_arrNavicells[iIdxCell];
        return(true);
    }
    } // public void DestructNavi()

    //@ Private
    //@ Build all Cells relationship with adjacent Cells. (N^2) CELL * CELL
    protected void buildupAdjacentAll(ref CNAVICELL[] arrNavicells)
    {
        for (int iSeqCell = 0; iSeqCell < arrNavicells.Length; ++iSeqCell)
        {
            CNAVICELL naviCell = (arrNavicells[iSeqCell]);
            BuildAdjacentATri(ref naviCell, ref arrNavicells);
        }

        //FORTEST
        //validateAllAdjcntCells(arrNavicells);
    }
Beispiel #8
0
    public void setLinkAllAdjs_simulate(int iSeqCell,
                                        int iLevelFromGoal,
                                        ref CNAVICELL[] arrnavicellall,
                                        ref List <int> listCellsCurrentLevel,
                                        ref List <int> listCellsNextLevel)
    {
        if (true == IsBlockCell())
        {
            return;
        }

        CNAVICELL.E_CELL_SIDEEDGE eEdgeAdj;
        bool bOverlappedWith = false, bComputeOK = false;

        for (int iEdge = 0; iEdge < 3; ++iEdge)
        {
            eEdgeAdj = (CNAVICELL.E_CELL_SIDEEDGE)iEdge;
            int iSeqCellAdj = m_arriAdjCells[iEdge];

            if (CNAVICELL.NULL_CELL == iSeqCellAdj)
            {
                continue;
            }

            CNAVICELL naviCellAdj = arrnavicellall[iSeqCellAdj];
            if (naviCellAdj.IsBlockCell() || naviCellAdj.IsGoalCell())
            {
                continue;
            }

            if (eEdgeAdj == m_eEdge_bestway)
            {
                continue;
            }

            if (CNAVICELL.NULL_LEVELFROMGOAL == naviCellAdj.m_iLevelToGoal)
            {
                bOverlappedWith = (-1 < listCellsCurrentLevel.BinarySearch(iSeqCellAdj));
                if (false == bOverlappedWith)
                {
                    bComputeOK = naviCellAdj.setLinkcomputeSimulate(iLevelFromGoal,
                                                                    iSeqCell);

                    if (true == bComputeOK)
                    {
                        listCellsNextLevel.Add(iSeqCellAdj);
                    }
                }
            } // if (CNAVICELL.NULL_LEVELFROMGOAL == naviCellAdj.m_iLevelToGoal)
        }     // for (int iEdge = 0; iEdge < 3; ++iEdge)
    }         // public void setLinkAllAdjs_simulate
    //  Every navicell have just only one shortest way to GOAL.
    public bool getPosWayToGoal(int iSeqCell_current, ref Vector3 v3PosDest)
    {
        if (iSeqCell_current > (int)m_arrNavicells.Length || iSeqCell_current < 0)
        {
            Debug.Log("iSeqCell_current>(int)m_arrNavicells.size()||iSeqCell_current<0");
            return(false);
        }

        CNAVICELL naviCell = m_arrNavicells[iSeqCell_current];

        if (naviCell.IsBlockCell())
        {
            return(false);
        }

        return(naviCell.getPos_nextWay(ref v3PosDest));
    }
    } // public bool getPosWayTo_Portal(	int iSeqCell_current, ref Vector3 v3PosDest )

    //@ Get adjacent Index Triangles validated.
    public void getAdjacentTris(int iSeqCell, ref List <int> listTrisAdj)
    {
        if (iSeqCell > m_arrNavicells.Length)
        {
            return;
        }

        CNAVICELL naviCellCurr = m_arrNavicells[iSeqCell];

        for (int iAdj = 0; iAdj < naviCellCurr.m_arriAdjCells.Length; ++iAdj)
        {
            int iAdjTri = naviCellCurr.m_arriAdjCells[iAdj];

            if (iAdjTri != CNAVICELL.NULL_CELL)
            {
                listTrisAdj.Add(iAdjTri);
            }
        }
    }
    //@ -Return:
    public bool getPosWayTo_Portal(int iSeqCell_current, Vector2[] arrv2PntObjBoundary, ref Vector3 v3PosDest)
    {
        if (iSeqCell_current > (int)m_arrNavicells.Length || iSeqCell_current < 0)
        {
            Debug.Log("iSeqCell_current>(int)m_arrNavicells.size()||iSeqCell_current<0");
            return(false);
        }

        CNAVICELL naviCellCurr = m_arrNavicells[iSeqCell_current];

        if (naviCellCurr.IsBlockCell())
        {
            return(false);
        }

        //@ 가시성을 고려한 최단 거리의 위치값 설정.
        setNaviPortal_forShortestWay(arrv2PntObjBoundary, ref naviCellCurr);

        return(naviCellCurr.getPos_nextWay(ref v3PosDest));
    } // public bool getPosWayTo_Portal(	int iSeqCell_current, ref Vector3 v3PosDest )
    } // protected bool BuildAdjacentATri

    // 함수:ConstructTrisToCells
    // 네비게이션을 위한 모든 셀들과 인접 셀들을 생성한다
    //@ Construct all adjacent Cells for navigation.
    protected void ConstructTrisToCells(List <CTRI> listTris_)
    {
        int iCntTris = listTris_.Count;

        m_arrNavicells = new CNAVICELL[iCntTris];   // Tri카운트 만큼 네비셀 생성

        for (int iTri = 0; iTri < iCntTris; iTri++)
        {
            CTRI triCurr = listTris_[iTri];

            CNAVICELL naviCell = new CNAVICELL();
            naviCell.InitializeNaviCell();  // 각 셀들의 초기화

            //@ Compute each middle edge to Center
            naviCell.SetComponentCell(iTri, triCurr);   // Tri 기본 정보를 네비셀에 전달 그리고 각각의 미들 엣지,센터를 계산
            m_arrNavicells[iTri] = naviCell;
        }

        buildupAdjacentAll(ref m_arrNavicells); // 인접 셀 빌드업
    }
    } // protected float differChangeRateBetweenVec3(Vector3 v3Way0, Vector3 v3Way1, Vector3 v3Way2)

    //@ search intersected point // faster then 3.x~4.x times average, prepare RayIntersect.
    public int intersectRay_inAdjs(int iSeqCell, Vector3 v3RayOrigin, Vector3 v3RayDir, ref Vector3 posIntersected_out)
    {
        if (CNAVICELL.NULL_CELL == iSeqCell)
        {
            return(CNAVICELL.NULL_CELL);
        }

        CNAVICELL navicell = m_arrNavicells[iSeqCell];

        int  iIdxIntersectedCell = CNAVICELL.NULL_CELL;
        bool bIntersectedCell    = false;

        bIntersectedCell = CMATH.IntersectRayTri_GetPos(
            v3RayOrigin,
            v3RayDir,
            navicell.m_arrv3PT,
            ref posIntersected_out);
        if (true == bIntersectedCell)
        {
            iIdxIntersectedCell = iSeqCell;
        }
        else
        {
            foreach (int iIterCell in navicell.m_arriAdjCells)
            {
                if (CNAVICELL.NULL_CELL != iIterCell)
                {
                    bIntersectedCell = m_arrNavicells[iIterCell].trilinkcell.IntersectRayTri(v3RayOrigin, v3RayDir, ref posIntersected_out);
                    if (true == bIntersectedCell)
                    {
                        iIdxIntersectedCell = iIterCell;

                        break;
                    }
                } // if (CNAVICELL.NULL_CELL != iSeqCell)
            }     // foreach(int iSeqCellNavi in navicell.m_arriAdjCells)
        }         // if (true == bIntersectedCell)

        return(iIdxIntersectedCell);
    } // public bool intersectRay_inAdjs(int iSeqCell, Vector3 v3RayOrigin, Vector3 v3RayDir, ref Vector3 posIntersected_out)
Beispiel #14
0
    protected bool extractNavicellToAdj(
        List <CTRI> listTris,
        CNAVICELL[] arrNavicells,
        ref CNAVICELL.CADJ_TRI[] arrAdjs)
    {
        int iCntNaviCell = arrNavicells.Length;

        if (iCntNaviCell < 1)
        {
            Debug.Log("if(iCntNaviCell < 1)");
            return(false);
        }

        arrAdjs = new CNAVICELL.CADJ_TRI[iCntNaviCell];

        for (int iSeqTri = 0; iSeqTri < iCntNaviCell; ++iSeqTri)
        {
            CNAVICELL naviCellCurr = arrNavicells[iSeqTri];
            arrAdjs[iSeqTri]     = naviCellCurr.getAdj();
            arrAdjs[iSeqTri].tri = listTris[iSeqTri];
        }
        return(true);
    }
    //@ For DEBUG, check all adjacent cells.
    protected void validateAllAdjcntCells(CNAVICELL[] arrNavicells)
    {
        string szOutputDebug;
        uint   uiCnt = 0;

        szOutputDebug  = "Validate All Adjacent Cell\n";
        szOutputDebug += "============================================================================";
        Debug.Log(szOutputDebug);
        szOutputDebug = "";

        int iCntCells = arrNavicells.Length;

        for (int iSeqCell = 0; iSeqCell < iCntCells; ++iCntCells, ++uiCnt)
        {
            CNAVICELL cellRight = arrNavicells[iSeqCell];

            //szOutputDebug = "\n " + uiCnt + ". TriSeq(" + cellRight.m_iSeq + ")";
            //            szOutputDebug +=  "AdjacentTri :";

            for (int iAdj = 0; iAdj < CNAVICELL.countSideEdge; ++iAdj)
            {
                int iAdjcntTri = cellRight.m_arriAdjCells[iAdj];

                szOutputDebug += "/i=" + iAdjcntTri;
            }

            szOutputDebug += "\n " + uiCnt + ". TriSeq(" + cellRight.seqCell + ")//";
        }
        Debug.Log(szOutputDebug);

        //validateAdjcnt_Iteration( 0, arrNavicells );

        szOutputDebug += "Check Call by NeiborTri";
        szOutputDebug += "============================================================================";
        Debug.Log(szOutputDebug);
        szOutputDebug = "";
    }
    //@ -Return:pre-calculated shortest cost middle edge position (way to goal) (when mappingnavigation).
    //  Every navicell have just only one shortest way to GOAL.
    public CNAVICELL.E_CELL_STATUS getPosCurrentWayToGoal(int iSeqCell_current, ref CCellWayto pntNavi_out)
    {
        if (iSeqCell_current > (int)m_arrNavicells.Length || iSeqCell_current < 0)
        {
            Debug.Log("!!!ERROR iSeqCell_current>(int)m_arrNavicells.size()||iSeqCell_current<0");

            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_NULL);
        }

        CNAVICELL naviCell  = m_arrNavicells[iSeqCell_current];
        Vector3   v3PosDest = Vector3.zero;

        bool bGetPos_nextWay = naviCell.getPos_nextWay(ref v3PosDest);

        if (false == bGetPos_nextWay || Vector3.zero == v3PosDest)
        {
            return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_NULL);
        }

        Vector3 posEdge0 = new Vector3(), posEdge1 = new Vector3();

        naviCell.getPntsOfEdgeBestway(ref posEdge0, ref posEdge1);

        pntNavi_out.setPntnavi(naviCell.seqCell,
                               naviCell.leveltogoal,
                               Vector3.zero,
                               v3PosDest,
                               posEdge0,
                               posEdge1,
                               posEdge0,
                               posEdge1,
                               naviCell.getPos_cellCenter(),
                               naviCell.dirCenterToGoal);

        return(CNAVICELL.E_CELL_STATUS.CELL_STATUS_ROAD);
    } // public bool getPosWayToGoal(int iSeqCell_current, ref CCellWayto pntNavi_out)
    } // public bool getPosWayToGoal(int iSeqCell_current, ref CCellWayto pntNavi_out)

    //@ -Return:
    public bool getPosWayTo_Portal(int iSeqCell_current, Vector2[] arrv2PntObjBoundary, ref CCellWayto pntNavi_out)
    {
        if (iSeqCell_current > (int)m_arrNavicells.Length || iSeqCell_current < 0)
        {
            Debug.Log("iSeqCell_current>(int)m_arrNavicells.size()||iSeqCell_current<0");
            return(false);
        }

        CNAVICELL naviCellCurr = m_arrNavicells[iSeqCell_current];

        //@ 가시성을 고려한 최단 거리의 위치값 설정.
        Vector3 v3PosDest       = new Vector3();
        bool    bGetPos_nextWay = setNaviPortal_forShortestWay(arrv2PntObjBoundary, ref naviCellCurr);

        if (false == bGetPos_nextWay)
        {
            return(false);
        }

        pntNavi_out._idxnavicell = naviCellCurr.seqCell;
        pntNavi_out._postoDest   = v3PosDest;

        return(true);
    }
    // Collect all blocks start to goal. And then buildup shortest way start to goal.
    // 처음 스타트 부터 골까지의 모든 네비 블럭을 모은다(가장 짧은 길을 택한다)
    static public void collectWayToGoalLinear(CNAVICELL[] arrNavicells_,
                                              CNAVICELL cellStart_,
                                              ref List <CNAVICELL> listSequenceCell_,
                                              ref CComputeEdgeBlock processorEdge_)
    {
        bool    bOrganizedComplete = false;
        Vector3 v3PntEdge0         = new Vector3();
        Vector3 v3PntEdge1         = new Vector3();

        CNAVICELL cellWay = cellStart_;

        bOrganizedComplete = false;

        listSequenceCell_.Add(cellWay); //First unit is startcell.

        //@ first collect all blocks start -> goal.
        while (false == bOrganizedComplete)
        {
            CTRI triWaytoGoal = cellWay.trilinkcell;

            //@ if Adjacent cell is NULL, add new EDGE list.    //이웃셀이 없다면 추가한다
            for (int iSeqAdj = 0; iSeqAdj < cellWay.m_arriAdjCells.Length; ++iSeqAdj)
            {
                int             iIdxAdj = cellWay.m_arriAdjCells[iSeqAdj];
                CTRI.E_TRI_EDGE eEdge   = (CTRI.E_TRI_EDGE)iSeqAdj;

                //@ Checkup adjacent Edge Tri    //
                if (CNAVICELL.NULL_CELL == iIdxAdj)
                {
                    triWaytoGoal.GetEdgePoint(eEdge, ref v3PntEdge0, ref v3PntEdge1);
                    processorEdge_.AddToBlockEdge(v3PntEdge0, v3PntEdge1);       //-> Add Edge to Block List
                }
                else
                {
                    CNAVICELL cellAdj = arrNavicells_[iIdxAdj];

                    //@ Adj cell is block cell, then into list.
                    if (cellAdj.IsBlockCell())
                    {
                        processorEdge_.AddToBlockEdge_Tri(cellAdj.trilinkcell, iIdxAdj); //-> Add Edge to Block List
                    }
                }
            } // for (int iAdj = 0; iAdj < naviCellNextWay.m_arriAdjCells.Length; ++iAdj)

            int iIdxCellBestWay = cellWay.getIdxCell_nextWay();

            if (CNAVICELL.NULL_CELL == iIdxCellBestWay)
            {
                return;
            }

            cellWay = arrNavicells_[iIdxCellBestWay];

            listSequenceCell_.Add(cellWay); // Last unit must be goalcell.

            if (true == cellWay.IsGoalCell())
            {
                bOrganizedComplete = true;
            }
        } // while (false == bOrganizedComplete)
    }     // protected void collectWayToGoalLinear()
    //@ Actually build up relationship with adjacent Cells and calculate cost of the way to GOAL.
    //@ Not acceptable 1 or more NULL CELL which status is CNAVICELL.NULL_CELL
    protected bool BuildAdjacentATri(ref CNAVICELL cellLeft,
                                     ref CNAVICELL[] arrNavicells)
    {
        if (true == cellLeft.DidSetAllAdjacent())
        {
            return(false);
        }

        int[] aruiIVleft = cellLeft.trilinkcell._arriIV;
        int[] aruiIVRight;
        bool  bFoundShared = false;
        int   iFoundShared = 0;

        int[] ariPointsShared_left  = new int[3];
        int[] ariPointsShared_right = new int[3];

        int iCntCells = arrNavicells.Length;

        for (int iSeqcell = 0; iSeqcell < iCntCells; ++iSeqcell)
        {
            CNAVICELL cellRight = arrNavicells[iSeqcell];
            CTRI      triRight_ = cellRight.trilinkcell;

            if (cellRight.seqCell == cellLeft.seqCell)
            {
                continue;
            }

            for (int i = 0; i < 3; ++i)
            {
                ariPointsShared_left[i] = ariPointsShared_right[i] = CNAVICELL.NULL_CELL;
            }

            aruiIVRight = triRight_._arriIV;

            iFoundShared = 0;
            int iSharedIV_left = 0, iSharedIV_right = 0;

            for (int iL = 0; iL < 3; ++iL)
            {
                for (int iR = 0; iR < 3; ++iR)
                {
                    if (aruiIVleft[iL] == aruiIVRight[iR])
                    {
                        ariPointsShared_left[iL]  = aruiIVleft[iL];
                        ariPointsShared_right[iR] = aruiIVRight[iR];

                        iSharedIV_left  = iSharedIV_left + iL;
                        iSharedIV_right = iSharedIV_right + iR;

                        ++iFoundShared;
                    }
                } // for( int iR=0; iR<3; ++iR )
            }     // for( int iL=0; iL<3; ++iL )

            bFoundShared = (iFoundShared > 1);
            if (true == bFoundShared)
            {
                if (iFoundShared > 2)
                {
                    break;
                }

                cellLeft.SetAdjacentCell(CNAVICELL.getTypeEdge(iSharedIV_left), cellRight.seqCell);
                cellRight.SetAdjacentCell(CNAVICELL.getTypeEdge(iSharedIV_right), cellLeft.seqCell);

                if (cellLeft.DidSetAllAdjacent() == true)
                {
                    break;
                }
            } // if( iFoundShared>1 )
        }     // for( it_=iterBegin; it_!=iterEnd; ++it_ )

        return(true);
    } // protected bool BuildAdjacentATri
    } // public bool intersectRay_inAdjs(int iSeqCell, Vector3 v3RayOrigin, Vector3 v3RayDir, ref Vector3 posIntersected_out)

    //@ Organize shortest way block edges only Current cell
    public bool setNaviPortal_forShortestWay(Vector2[] arrv2PntObjBoundary, ref CNAVICELL cellWayStart)
    {
        if (true == cellWayStart.useWaytoPortal)
        {
            return(true);
        }

        List <CNAVICELL> listSequenceCell = new List <CNAVICELL>();

        collectWayToGoalLinear(m_arrNavicells, cellWayStart, ref listSequenceCell, ref m_computeEdgeBlock);
        if (listSequenceCell.Count < 2)
        {
            return(true);
        }


        Vector3 v3PntPrev = new Vector3();
        Vector3 v3PntCurr = new Vector3();
        Vector3 v3PntNext = new Vector3();

        int       iLenSeq = listSequenceCell.Count;
        int       iSeqIteration = 0;
        CNAVICELL cellGOAL = listSequenceCell[iLenSeq - 1];
        CNAVICELL cellNext, cellPrev;

        bool bCrosswithBlock       = false;
        bool bSetNewPortalPosition = false;

        Vector3[] arrv3Pnt_Cell_start = new Vector3[cellWayStart.m_arrv3PT.Length];
        Array.Copy(cellWayStart.m_arrv3PT, arrv3Pnt_Cell_start, cellWayStart.m_arrv3PT.Length);
        CMATH.rescaleVertices(ref arrv3Pnt_Cell_start, DFLT_ADJUST_SCALE_FOR_VISIBLECHECK);

        foreach (CNAVICELL cellCurr in listSequenceCell)
        {
            int iSeqCurr = iSeqIteration++;

            if (0 == iSeqCurr)
            {
                continue;
            }

            if (cellGOAL == cellCurr)
            {
                cellWayStart.SetPortalPosition(cellGOAL.seqCell, cellGOAL.getPos_cellCenter());
                bSetNewPortalPosition = true;
                break;
            }

            cellPrev = listSequenceCell[iSeqCurr - 1];
            cellNext = listSequenceCell[iSeqCurr + 1];

            cellCurr.getPos_BestWay_onEdge(ref v3PntCurr);
            cellNext.getPos_BestWay_onEdge(ref v3PntNext);
            cellPrev.getPos_BestWay_onEdge(ref v3PntPrev);

            bCrosswithBlock = false;
            foreach (Vector3 v3PntCell in arrv3Pnt_Cell_start)
            {
                if (m_computeEdgeBlock.crossBlockIteration(v3PntCell, v3PntNext))
                {
                    bCrosswithBlock = true;
                    break;
                }
            }

            //@ Set Portal
            if (true == bCrosswithBlock)
            {
                cellWayStart.SetPortalPosition(cellCurr.seqCell, v3PntCurr);

                bSetNewPortalPosition = true;
                break;
            }

            Vector2 v2PntNext = CMATH.ConvertToV2_Y(v3PntNext);
            foreach (Vector2 v2PntObj in arrv2PntObjBoundary)
            {
                //@ Cross At least 1 mo
                if (true == m_computeEdgeBlock.crossBlockIteration(v2PntObj, v2PntNext))
                {
                    bCrosswithBlock = true;
                    break;
                }
            }

            //@ Set Portal -2
            if (true == bCrosswithBlock)
            {
                cellWayStart.SetPortalPosition(cellCurr.seqCell, v3PntCurr);

                bSetNewPortalPosition = true;
                break;
            }
        } // foreach (CNAVICELL cellCurr in listSequenceCell)

        listSequenceCell.Clear();
        listSequenceCell = null;

        return(bSetNewPortalPosition);
    } // public bool setNaviPortal_forShortestWay(int iSeqCell)
    }     // public void collectWayToGoalLinear

    //@ Organize shortest way block edges startcell to goalcell.
    public bool collectWay_allStartsToGoal(CTriCollector tricollector, ref CNAVICELL[] arrSequenceCellforPortal)
    {
        if (tricollector.m_listTris_naviStart.Count < 1)
        {
            return(false);
        }

        if (tricollector.m_listTris_naviGoal.Count < 1)
        {
            return(false);
        }

        arrSequenceCellforPortal = null;

        Vector3 v3PntStart_ = new Vector3();
        Vector3 v3PntEnd_   = new Vector3();

        Vector3 v3PntPortal = new Vector3();

        List <CNAVICELL> listSequenceCell = new List <CNAVICELL>();

        //@ each start cell
        foreach (int iSeqTriStart in tricollector.m_listTris_naviStart)
        {
            CNAVICELL cellWayStart = m_arrNavicells[iSeqTriStart];

            //@ First Collect all blocks start to goal. And then buildup shortest way start to goal.
            collectWayToGoalLinear(m_arrNavicells, cellWayStart, ref listSequenceCell, ref m_computeEdgeBlock);

            //@ Organize Start -> Goal
            if (listSequenceCell.Count > 2)
            {
                int iLenSeq = listSequenceCell.Count;
                int iSeqIteration = 0, iSeqPortalSpot = 0;
                v3PntStart_ = listSequenceCell[0].poscenterofcell;
                CNAVICELL cellGOAL        = listSequenceCell[iLenSeq - 1];
                bool      bCrosswithBlock = false;
                foreach (CNAVICELL cellCurr in listSequenceCell)
                {
                    int iSeqCurr = iSeqIteration++;

                    if (cellCurr == cellGOAL)
                    {
                        break;
                    }

                    cellCurr.getPos_nextWay(ref v3PntEnd_);

                    bCrosswithBlock = m_computeEdgeBlock.crossBlockIteration(v3PntStart_, v3PntEnd_);
                    if (true == bCrosswithBlock)
                    {
                        iSeqPortalSpot = iSeqCurr - 1;

                        if (listSequenceCell.Count <= iSeqPortalSpot || iSeqPortalSpot < 0)
                        {
                            continue;
                        }

                        listSequenceCell[iSeqPortalSpot].getPos_nextWay(ref v3PntPortal);

                        ////@ Some problem this, have to solve.
                        //for (int iCellSeq = iSeqPortalSpot__ + 1; iCellSeq < iSeqPortalSpot; ++iCellSeq)
                        //{
                        //    listSequenceCell[iCellSeq].SetPortalPosition(iSeqPortalSpot__, v3PntPortal);
                        //} //for (int iCellSeq = iSeqPortalSpot; iCellSeq < iSeqCurr - 1; ++iCellSeq)

                        v3PntStart_ = v3PntPortal;
                    } // if (true == bCrosswithBlock)
                }     // foreach (CNAVICELL cellCurr in listSequenceCell)

                int iSeqCopyTo = 0;
                if (null == arrSequenceCellforPortal)
                {
                    arrSequenceCellforPortal = new CNAVICELL[listSequenceCell.Count];
                }
                else
                {
                    iSeqCopyTo = arrSequenceCellforPortal.Length;
                    Array.Resize(ref arrSequenceCellforPortal, arrSequenceCellforPortal.Length + listSequenceCell.Count);
                } // if (null == arrSequenceCellforPortal)

                listSequenceCell.CopyTo(arrSequenceCellforPortal, iSeqCopyTo);
                listSequenceCell.Clear();
            } // if(listSequenceCell.Count > 2)
        }     // foreach(int iSeqTriStart in m_listCellsIdxStart)

        listSequenceCell.Clear();
        listSequenceCell = null;

        return(true);
    } // protected bool collectWay_allStartsToGoal()