Example #1
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 #2
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 #3
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);
        }