// this function sets up material properties used by functions provided in TerrainTool.cginc
        public static void SetupTerrainToolMaterialProperties(
            PaintContext paintContext,
            BrushTransform brushXform,     // the brush transform to terrain space (of paintContext.originTerrain)
            Material material)
        {
            // BrushUV = f(terrainSpace.xz) = f(g(pc.uv))
            //   f(ts.xy) = ts.x * brushXform.X + ts.y * brushXform.Y + brushXform.Origin
            //   g(pc.uv) = ts.xz = pcOrigin + pc.uv * pcSize
            //   f(g(pc.uv)) == (pcOrigin + pc.uv * pcSize).x * brushXform.X + (pcOrigin + pc.uv * pcSize).y * brushXform.Y + brushXform.Origin
            //   f(g(pc.uv)) == (pcOrigin.x + pc.u * pcSize.x) * brushXform.X + (pcOrigin.y + pc.v * pcSize.y) * brushXform.Y + brushXform.Origin
            //   f(g(pc.uv)) == (pcOrigin.x * brushXform.X) + (pc.u * pcSize.x) * brushXform.X + (pcOrigin.y * brushXform.Y) + (pc.v * pcSize.y) * brushXform.Y + brushXform.Origin
            //   f(g(pc.uv)) == pc.u * (pcSize.x * brushXform.X) + pc.v * (pcSize.y * brushXform.Y) + (brushXform.Origin + (pcOrigin.x * brushXform.X) + (pcOrigin.y * brushXform.Y))

            // pcOrigin =   (pc.pixelRect.xyMin - 0.5) * pc.pixelSize.xy
            // pcSize =     (pc.pixelRect.wh) * pc.pixelSize.xy

            // paint context origin in terrain space
            // (note this is the UV space origin and size, not the mesh origin & size)
            float pcOriginX = (paintContext.pixelRect.xMin - 0.5f) * paintContext.pixelSize.x;
            float pcOriginZ = (paintContext.pixelRect.yMin - 0.5f) * paintContext.pixelSize.y;
            float pcSizeX   = (paintContext.pixelRect.width) * paintContext.pixelSize.x;
            float pcSizeZ   = (paintContext.pixelRect.height) * paintContext.pixelSize.y;

            Vector2 scaleU = pcSizeX * brushXform.targetX;
            Vector2 scaleV = pcSizeZ * brushXform.targetY;
            Vector2 offset = brushXform.targetOrigin + pcOriginX * brushXform.targetX + pcOriginZ * brushXform.targetY;

            material.SetVector("_PCUVToBrushUVScales", new Vector4(scaleU.x, scaleU.y, scaleV.x, scaleV.y));
            material.SetVector("_PCUVToBrushUVOffset", new Vector4(offset.x, offset.y, 0.0f, 0.0f));
        }
        public static BrushTransform CalculateBrushTransform(Terrain terrain, Vector2 brushCenterTerrainUV, float brushSize, float brushRotationDegrees)
        {
            float          f           = brushRotationDegrees * 0.0174532924f;
            float          num         = Mathf.Cos(f);
            float          num2        = Mathf.Sin(f);
            Vector2        vector      = new Vector2(num, -num2) * brushSize;
            Vector2        vector2     = new Vector2(num2, num) * brushSize;
            Vector3        size        = terrain.terrainData.size;
            Vector2        a           = brushCenterTerrainUV * new Vector2(size.x, size.z);
            Vector2        brushOrigin = a - 0.5f * vector - 0.5f * vector2;
            BrushTransform result      = new BrushTransform(brushOrigin, vector, vector2);

            return(result);
        }
        // returns a transform from terrain space to brush UV
        public static BrushTransform CalculateBrushTransform(
            Terrain terrain, Vector2 brushCenterTerrainUV, float brushSize, float brushRotationDegrees)
        {
            float   rotationRadians = brushRotationDegrees * Mathf.Deg2Rad;
            float   cos             = Mathf.Cos(rotationRadians);
            float   sin             = Mathf.Sin(rotationRadians);
            Vector2 brushU          = new Vector2(cos, -sin) * brushSize;
            Vector2 brushV          = new Vector2(sin, cos) * brushSize;

            // calculate brush origin
            Vector3 terrainSize             = terrain.terrainData.size;
            Vector2 brushCenterTerrainSpace = brushCenterTerrainUV * new Vector2(terrainSize.x, terrainSize.z);
            Vector2 brushOrigin             = brushCenterTerrainSpace - 0.5f * brushU - 0.5f * brushV;

            BrushTransform xform = new BrushTransform(brushOrigin, brushU, brushV);

            return(xform);
        }
        public static void SetupTerrainToolMaterialProperties(PaintContext paintContext, BrushTransform brushXform, Material material)
        {
            float   d       = ((float)paintContext.pixelRect.xMin - 0.5f) * paintContext.pixelSize.x;
            float   d2      = ((float)paintContext.pixelRect.yMin - 0.5f) * paintContext.pixelSize.y;
            float   d3      = (float)paintContext.pixelRect.width * paintContext.pixelSize.x;
            float   d4      = (float)paintContext.pixelRect.height * paintContext.pixelSize.y;
            Vector2 vector  = d3 * brushXform.targetX;
            Vector2 vector2 = d4 * brushXform.targetY;
            Vector2 vector3 = brushXform.targetOrigin + d * brushXform.targetX + d2 * brushXform.targetY;

            material.SetVector("_PCUVToBrushUVScales", new Vector4(vector.x, vector.y, vector2.x, vector2.y));
            material.SetVector("_PCUVToBrushUVOffset", new Vector4(vector3.x, vector3.y, 0f, 0f));
        }