Example #1
0
        //x ~ (0, setting.maxX * power(2, subdivision)), z ~ (0, setting.maxZ * power(2, subdivision))
        public MPPathNode GetStandablePathNode(int u, int v, ushort refH)
        {
            float        centerx     = 0;
            float        centerz     = 0;
            int          subdivision = setting.subdivision;
            QuadTreeLeaf leaf        = GetLeaf(u, v, ref centerx, ref centerz, ref subdivision);

            if (leaf == null || leaf.Slices == null)
            {
                return(null);
            }
            for (uint i = (uint)leaf.Slices.Length - 1; i > 0; --i)
            {
                ulong  currentSlice  = leaf.Slices[i];
                byte   currentf      = SliceAccessor.flag(currentSlice);
                ushort currentheight = SliceAccessor.heightGrade(currentSlice);
                ulong  lowerSlice    = leaf.Slices[i - 1];
                ushort lowerf        = SliceAccessor.flag(lowerSlice);
                ushort lowerheight   = SliceAccessor.heightGrade(lowerSlice);
                if ((currentf & SliceAccessor.SliceCeiling) > 0)
                {
                    continue;
                }
                if (refH >= currentheight ||
                    ((lowerf & SliceAccessor.SliceCeiling) > 0 && refH >= lowerheight))
                {//pillar roof
                    return(MPPathNodePool.Pop(leaf.Header, u, v, i, subdivision, setting.subdivision,
                                              centerx, centerz, currentSlice));
                }
            }
            ulong floorSlice = leaf.Slices[0];

            return(MPPathNodePool.Pop(leaf.Header, u, v, 0, subdivision, setting.subdivision,
                                      centerx, centerz, floorSlice));
        }
Example #2
0
        private short GetSlope(ulong start, ulong end, float delta, float sliceThickness)
        {
            uint startH = SliceAccessor.heightGrade(start);
            uint endH   = SliceAccessor.heightGrade(end);

            return((short)(SliceAccessor.slopeMagnify * sliceThickness * (endH - startH) / delta));
        }
Example #3
0
        public void GetPathNeighbours(MPPathNode current, int maxX, int maxZ, MPNeigbours neighbours)
        {
            ulong[] curSlices = HeightSlicePool.GetSlices(current.SliceHeader);
            if (curSlices == null)
            {
                return;
            }
            //get current ceiling, where I can't go across
            ushort maxH = ushort.MaxValue;

            if (current.HIdx < curSlices.Length - 1)
            {
                ulong  higherSlice  = curSlices[current.HIdx + 1];
                ushort higherf      = SliceAccessor.flag(higherSlice);
                ushort higherheight = SliceAccessor.heightGrade(higherSlice);
                if ((higherf & SliceAccessor.SliceCeiling) > 0)
                {
                    maxH = higherheight;
                }
            }
            for (int u = current.BoundaryXMin; u <= current.BoundaryXMax; ++u)
            {
                if (u < 0 || u >= maxX)
                {
                    continue;
                }
                if (current.BoundaryZMin >= 0 && current.BoundaryZMin < maxZ)
                {
                    GetPathNeighbour(current.HeightGrade, maxH, u, current.BoundaryZMin, neighbours);
                }
                if (current.BoundaryZMax >= 0 && current.BoundaryZMax < maxZ)
                {
                    GetPathNeighbour(current.HeightGrade, maxH, u, current.BoundaryZMax, neighbours);
                }
            }
            for (int v = current.BoundaryZMin; v <= current.BoundaryZMax; ++v)
            {
                if (v < 0 || v >= maxZ)
                {
                    continue;
                }
                if (current.BoundaryXMin >= 0 && current.BoundaryXMin < maxX)
                {
                    GetPathNeighbour(current.HeightGrade, maxH, current.BoundaryXMin, v, neighbours);
                }
                if (current.BoundaryXMax >= 0 && current.BoundaryXMax < maxX)
                {
                    GetPathNeighbour(current.HeightGrade, maxH, current.BoundaryXMax, v, neighbours);
                }
            }
        }
Example #4
0
        //detailed x, z
        //dx ~ (0, setting.maxX * power(2, subdivision)), dx ~ (0, setting.maxZ * power(2, subdivision))
        public void Reset(uint header, int dx, int dz, uint ih, int sub, int maxSub,
                          float centerx, float centerz, ulong val)
        {
            SliceHeader = header;
            HIdx        = ih;
            Subdivision = sub;
            X           = centerx;
            Z           = centerz;
            HeightGrade = SliceAccessor.heightGrade(val);
            Flag        = SliceAccessor.flag(val);
            mSlopeU     = SliceAccessor.slopeUGrade(val) / SliceAccessor.slopeMagnify;
            mSlopeV     = SliceAccessor.slopeVGrade(val) / SliceAccessor.slopeMagnify;
            //boundary
            BoundaryXMin = 0;
            BoundaryZMin = 0;
            int detail = 1 << sub;

            if (sub == 0)
            {
                BoundaryXMin = dx;
                BoundaryZMin = dz;
            }
            else
            {
                for (int s = maxSub; s >= sub; --s)
                {
                    detail = 1 << s;
                    int u = dx >> s; // x / power(2, subdivision);
                    int v = dz >> s;
                    BoundaryXMin += u * detail;
                    BoundaryZMin += v * detail;
                    dx           -= u * detail;
                    dz           -= v * detail;
                }
            }
            BoundaryXMax  = BoundaryXMin + detail;
            BoundaryZMax  = BoundaryZMin + detail;
            BoundaryXMin -= 1;
            BoundaryZMin -= 1;
        }
Example #5
0
        //dynamically add pillars in
        //x ~ (0, setting.maxX * power(2, subdivision)), x ~ (0, setting.maxZ * power(2, subdivision))
        public void AddPillar(int subdivision, int x, int z, OrderedSlices rawSlices)
        {
            //first grade
            int u    = x >> subdivision; // x / power(2, subdivision);
            int v    = z >> subdivision;
            int subx = x - u * (1 << subdivision);
            int subz = z - v * (1 << subdivision);

            --subdivision;
            int idx = (subx >> subdivision) * 2 + (subz >> subdivision);

            if (subdivision > 0)
            {
                if (Children[idx] is QuadTreeLeaf)
                {
                    SubdividLeaf(idx);
                }
                QuadTreeNode node = (QuadTreeNode)Children[idx];
                node.AddPillar(subdivision, subx, subz, rawSlices);
            }
            else
            {
                if (Children[idx] is QuadTreeNode)
                {
                    MPLog.LogError("AddPillar leaf still a tree : " + subdivision);
                    return;
                }
                QuadTreeLeaf leaf = (QuadTreeLeaf)Children[idx];
                if (leaf.Slices != null)
                {
                    HeightSlicePool.Push(leaf.Header, leaf.Slices);
                }
                leaf.Reset(rawSlices.Count, rawSlices.HashValue);
                for (int i = 0; i < rawSlices.Count; ++i)
                {
                    leaf.Slices[i] = SliceAccessor.packVal(rawSlices[i].heightGrade, 0, 0, rawSlices[i].flag);
                }
            }
        }
Example #6
0
        public void Unify(float startHeight, float heightPerGrade)
        {
            SortSlices();
            if (Count == 0)
            {
                MPLog.LogError("pillar is empty.");
            }
            //merge the slices, slices should be floor|ceiling|floor|ceiling....|floor
            bool bNeedMerge = true;

            while (bNeedMerge && Count > 0)
            {
                bNeedMerge = false;
                for (int i = 0; i < Count - 1; ++i)
                {
                    if (this[i].flag == this[i + 1].flag)
                    {
                        if ((this[i].flag & SliceAccessor.SliceCeiling) > 0)
                        {//ceiling use lower one
                            RemoveAt(i + 1);
                        }
                        else
                        {//floor use higher one
                            RemoveAt(i);
                        }
                        bNeedMerge = true;
                        break;
                    }
                }
            }
            HashValue = 0;
            for (int i = 0; i < Count; ++i)
            {
                RawSlice slice = this[i];
                slice.heightGrade = (ushort)Math.Ceiling((slice.height - startHeight) / heightPerGrade);
                HashValue        += SliceAccessor.packVal(slice.heightGrade, 0, 0, slice.flag);
            }
        }
Example #7
0
        private void GetLeafDisplaySlice(ulong[] slices, float startx, float startz, float sizex, float sizez, int x, int z,
                                         List <DisplaySlice> lSlices)
        {
            float minx = startx + sizex * x;
            float minz = startz + sizez * z;
            float maxx = startx + sizex * (x + 1);
            float maxz = startz + sizez * (z + 1);

            for (int i = 0; i < slices.Length; ++i)
            {
                ulong        rawSlice = slices[i];
                DisplaySlice slice    = new DisplaySlice();
                slice.height = setting.heightValRange[0] +
                               SliceAccessor.heightGrade(rawSlice) * setting.heightPerGrade;
                slice.flag = SliceAccessor.flag(rawSlice);
                slice.min  = new float[2] {
                    minx, minz
                };
                slice.max = new float[2] {
                    maxx, maxz
                };
                lSlices.Add(slice);
            }
        }
Example #8
0
        private void GetPathNeighbour(ushort curH, ushort maxH, int u, int v, MPNeigbours neighbours)
        {
            float        centerx     = 0;
            float        centerz     = 0;
            int          subdivision = setting.subdivision;
            QuadTreeLeaf leaf        = GetLeaf(u, v, ref centerx, ref centerz, ref subdivision);

            if (leaf == null || leaf.Slices == null)
            {
                return;
            }
            //bigger subdivision may has the same slice structure, add only one
            if (neighbours.Contains(leaf.Header))
            {
                return;
            }
            //each height slice could be a neighbour
            if (leaf.Slices.Length == 1)
            {
                ulong  floorSlice = leaf.Slices[0];
                ushort height     = SliceAccessor.heightGrade(floorSlice);
                byte   flag       = SliceAccessor.flag(floorSlice);
                if (CanMove2Neighbour(setting, curH, maxH, height, ushort.MaxValue))
                {
                    neighbours.Add(leaf.Header, u, v, 0, subdivision, setting.subdivision, centerx, centerz, floorSlice);
                }
            }
            else
            {
                for (uint i = 0; i < leaf.Slices.Length - 1; ++i)
                {
                    ulong  currentSlice  = leaf.Slices[i];
                    byte   currentf      = SliceAccessor.flag(currentSlice);
                    ushort currentheight = SliceAccessor.heightGrade(currentSlice);
                    ulong  higherSlice   = leaf.Slices[i + 1];
                    byte   higherf       = SliceAccessor.flag(higherSlice);
                    ushort higherheight  = SliceAccessor.heightGrade(higherSlice);
                    if (i == leaf.Slices.Length - 2 && (higherf & SliceAccessor.SliceCeiling) == 0)
                    {//pillar roof
                        if (CanMove2Neighbour(setting, curH, maxH, higherheight, ushort.MaxValue))
                        {
                            neighbours.Add(leaf.Header, u, v, i + 1, subdivision, setting.subdivision,
                                           centerx, centerz, higherSlice);
                        }
                        break;
                    }
                    if ((currentf & SliceAccessor.SliceCeiling) > 0)
                    {
                        continue;
                    }
                    ushort currentMaxH = ushort.MaxValue;
                    if ((higherf & SliceAccessor.SliceCeiling) > 0)
                    {//check standable
                        float holeHeight = (higherheight - currentheight) * setting.heightPerGrade;
                        if (holeHeight < setting.boundHeight)
                        {
                            continue;
                        }
                        currentMaxH = higherheight;
                    }
                    if (CanMove2Neighbour(setting, curH, maxH, currentheight, currentMaxH))
                    {
                        neighbours.Add(leaf.Header, u, v, i, subdivision, setting.subdivision,
                                       centerx, centerz, currentSlice);
                    }
                }
            }
        }
Example #9
0
        private QuadTreeLeaf Combine(float dx, float dz, float sliceThickness, float slopeErr)
        {
            if (Children[0] == null || !(Children[0] is QuadTreeLeaf))
            {
                return(null);
            }
            QuadTreeLeaf leaf = (QuadTreeLeaf)Children[0];

            for (int i = 1; i < Children.Length; ++i)
            {
                if (Children[i] == null || !(Children[i] is QuadTreeLeaf))
                {
                    return(null);
                }
                if (!leaf.IsCombinable((QuadTreeLeaf)Children[i]))
                {
                    return(null);
                }
            }
            for (int s = 0; s < leaf.Slices.Length; ++s)
            {
                ulong leafS = leaf.Slices[s];
                byte  flag  = SliceAccessor.flag(leafS);
                //x axis
                short slopeU  = GetSlope(leafS, ((QuadTreeLeaf)Children[1]).Slices[s], dx, sliceThickness);
                short slopeU1 = GetSlope(((QuadTreeLeaf)Children[2]).Slices[s], ((QuadTreeLeaf)Children[3]).Slices[s],
                                         dx, sliceThickness);
                if ((slopeU != 0 && slopeU1 != 0 && Math.Abs(slopeU1 - slopeU) > slopeErr * SliceAccessor.slopeMagnify))
                {
                    return(null);
                }
                slopeU += slopeU1; slopeU /= 2;
                //z axis
                short slopeV  = GetSlope(leafS, ((QuadTreeLeaf)Children[2]).Slices[s], dz, sliceThickness);
                short slopeV1 = GetSlope(((QuadTreeLeaf)Children[1]).Slices[s], ((QuadTreeLeaf)Children[3]).Slices[s],
                                         dz, sliceThickness);
                if ((slopeV != 0 && slopeV1 != 0 && Math.Abs(slopeV1 - slopeV) > slopeErr * SliceAccessor.slopeMagnify))
                {
                    return(null);
                }
                slopeV += slopeV1; slopeV /= 2;
                ushort updateH = 0;
                for (int i = 0; i < Children.Length; ++i)
                {
                    QuadTreeLeaf l  = (QuadTreeLeaf)Children[i];
                    ulong        lS = l.Slices[s];
                    if (leaf.HashVal != l.HashVal)
                    {
                        byte  f  = SliceAccessor.flag(lS);
                        short sU = SliceAccessor.slopeUGrade(lS);
                        short sV = SliceAccessor.slopeVGrade(lS);
                        //floor cant match ceiling
                        if (flag != f)
                        {
                            return(null);
                        }
                        //slope error
                        if ((sU != 0 && Math.Abs(sU - slopeU) > slopeErr * SliceAccessor.slopeMagnify) ||
                            (sV != 0 && Math.Abs(sV - slopeV) > slopeErr * SliceAccessor.slopeMagnify))
                        {
                            return(null);
                        }
                    }
                    updateH += SliceAccessor.heightGrade(lS);
                }
                updateH      >>= 2;//average height
                leaf.Slices[s] = SliceAccessor.packVal(updateH, slopeU, slopeV, flag);
            }
            leaf.RefreshHash();
            return(leaf);
        }