Esempio n. 1
0
    /// <summary>
    /// 获取指定方向移动的最佳距离
    /// </summary>
    /// <param name="sdf"></param>
    /// <param name="pos">起始位置</param>
    /// <param name="dir">方向</param>
    /// <param name="speed">速度</param>
    /// <param name="radius">碰撞半径</param>
    /// <returns></returns>
    public static TSVector2 GetVaildPositionBySDF(this SDFRawData sdf, TSVector2 pos, TSVector2 dir, FP speed, FP radius)
    {
        TSVector2 newPos = pos + dir * speed;
        FP        sd     = Sample(sdf, newPos);

        //距离障碍物太近,不可行走
        if (sd < radius)
        {
            TSVector2 gradient  = Gradient(sdf, newPos);
            TSVector2 asjustDir = dir - gradient * TSVector2.Dot(gradient, dir);
            newPos = pos + asjustDir.normalized * speed;
            //多次迭代
            for (int i = 0; i < 3; ++i)
            {
                sd = Sample(sdf, newPos);
                if (sd >= radius)
                {
                    break;
                }
                newPos += Gradient(sdf, newPos) * (radius - sd);
            }
            //避免往返
            if (TSVector2.Dot(newPos - pos, dir) < FP.Zero)
            {
                newPos = pos;
            }
        }
        return(newPos);
    }
Esempio n. 2
0
        public static SDFRawData SceneToSDF(GameObject go, Vector3 validPos, int layerMask = -1)
        {
            float cellSize = 0.25f;
            float sdfScale = 0.25f;
            var   bounds   = GetBoundsFromGameObject(go);

            bounds = AlignBounds(bounds);
            var voxel = Creat(bounds, cellSize);

            AddGameObject(voxel, go, layerMask);
            var        heightfield = VoxelToHeightfield(voxel);
            var        grid        = HeightfieldToPlaneGrid(heightfield, 0, 2);
            Vector2Int size        = new Vector2Int(voxel.Size.x, voxel.Size.z);
            var        pos         = Vector3Int.CeilToInt((validPos - voxel.Bounds.min) / voxel.CellSize);

            grid.Mask = CalcClosePoint(grid.Mask, size, new Vector2Int(pos.x, pos.z));

            grid = FilterEdge(grid);
            //生成sdf信息
            sbyte[] data = new sbyte[grid.Width * grid.Length];
            SDFGenerate.Gen(grid.Mask, grid.Width, grid.Length, cellSize, sdfScale, data);
            SDFRawData sdf   = new SDFRawData();
            TSVector2  orign = new TSVector2(grid.OriginPoint.x, grid.OriginPoint.y);

            sdf.Init(grid.Width, grid.Length, cellSize, sdfScale, orign, data);
            return(sdf);
        }
Esempio n. 3
0
    public static RectInt ToRect(this SDFRawData sdf, TSVector2 start, TSVector2 end)
    {
        TSVector2 min = new TSVector2(TSMath.Min(start.x, end.x), TSMath.Min(start.y, end.y));
        TSVector2 max = new TSVector2(TSMath.Max(start.x, end.x), TSMath.Max(start.y, end.y));

        return(new RectInt(sdf.FloorToGrid(min), sdf.CeilingToGrid(max)));
    }
Esempio n. 4
0
    //求位置的梯度方向
    public static TSVector2 Gradient(this SDFRawData sdf, TSVector2 pos)
    {
        FP delat = FP.ONE;
        FP x     = Sample(sdf, pos.x + delat, pos.y) - Sample(sdf, pos.x - delat, pos.y);
        FP y     = Sample(sdf, pos.x, pos.y + delat) - Sample(sdf, pos.x, pos.y - delat);

        return(new TSVector2(FP.Half * x, FP.Half * y));
    }
Esempio n. 5
0
        public static Texture2D SDFToTexture(SDFRawData sdf)
        {
            Texture2D texture = new Texture2D(sdf.Width, sdf.Heigh);

            for (int i = 0; i < texture.width; ++i)
            {
                for (int j = 0; j < texture.height; ++j)
                {
                    texture.SetPixel(i, j, sdf[i, j] < 0 ? Color.black : Color.white);
                }
            }
            return(texture);
        }
Esempio n. 6
0
        public static void SDFRenderToTexture(SDFRawData sdf, Texture2D texture)
        {
            float xScale = (sdf.Width / (float)texture.width) * (float)sdf.Grain;
            float yScale = (sdf.Heigh / (float)texture.height) * (float)sdf.Grain;

            for (int i = 0; i < texture.width; ++i)
            {
                for (int j = 0; j < texture.height; ++j)
                {
                    FP sd = sdf.Sample(new TSVector2(i * xScale, j * yScale));
                    texture.SetPixel(i, j, sd < 0 ? Color.black : Color.white);
                }
            }
        }
Esempio n. 7
0
    public static Texture2D ToGrayTexture(SDFRawData sdf)
    {
        Texture2D texture = new Texture2D(sdf.Width, sdf.Height);

        for (int i = 0; i < sdf.Width; ++i)
        {
            for (int j = 0; j < sdf.Height; ++j)
            {
                float val   = ((float)sdf[i, j] - short.MinValue) / 65536;
                Color color = new Color(val, val, val, 1);
                texture.SetPixel(i, j, color);
            }
        }
        return(texture);
    }
Esempio n. 8
0
    /// <summary>
    /// SDF 采样
    /// </summary>
    /// <param name="sdf">sdf数据</param>
    /// <param name="pos">相对于sdf原点的位置</param>
    /// <returns>采样后对应位置的SD值</returns>
    public static FP Sample(this SDFRawData sdf, TSVector2 pos)
    {
        pos /= sdf.Grain;
        int x   = (int)FP.Floor(pos.x);
        int y   = (int)FP.Floor(pos.y);
        int idx = x + y * sdf.Width;
        FP  rx  = pos.x - x;
        FP  ry  = pos.y - y;
        //2 3
        //0 1
        FP v0 = sdf[idx];
        FP v1 = sdf[idx + 1];
        FP v2 = sdf[idx + sdf.Width];
        FP v3 = sdf[idx + sdf.Width + 1];

        return((v0 * (1 - rx) + v1 * rx) * (1 - ry) + (v2 * (1 - rx) + v3 * rx) * ry);
    }
Esempio n. 9
0
    //圆盘投射,获取最远可移动的位置
    public static TSVector2 DiskCast(this SDFRawData sdf, TSVector2 origin, TSVector2 dir, FP radius, FP maxDistance)
    {
        FP t = FP.Zero;

        while (true)
        {
            TSVector2 p  = origin + dir * t;
            FP        sd = Sample(sdf, p);
            if (sd <= radius)
            {
                return(p);
            }
            t += (sd - radius);
            if (t >= maxDistance)
            {
                return(origin + dir * maxDistance);
            }
        }
    }
Esempio n. 10
0
 public SDFMap(SDFRawData sdf)
 {
     SDF = sdf;
 }
Esempio n. 11
0
 public static TSVector2 WorldToLocal(this SDFRawData sdf, TSVector2 pos)
 {
     return(pos - sdf.Origin);
 }
Esempio n. 12
0
 public static FP Sample(this SDFRawData sdf, FP posX, FP posY)
 {
     return(Sample(sdf, new TSVector2(posX, posY)));
 }
Esempio n. 13
0
 public static Vector2Int CeilingToGrid(this SDFRawData sdf, TSVector2 positin)
 {
     positin /= sdf.Grain;
     return(new Vector2Int((int)FP.Ceiling(positin.x), (int)FP.Ceiling(positin.y)));
 }