コード例 #1
0
        /// <summary>
        /// Return if the position is inside of the triangle
        /// </summary>
        /// <param name="_position"></param>
        /// <returns></returns>
        public bool IsInTriangle(Vector3 _position, Triangle _triangle)
        {
            Barycentric _barycentric = new Barycentric(NavigationDatas.Vertices[_triangle.Vertices[0]],
                                                       NavigationDatas.Vertices[_triangle.Vertices[1]],
                                                       NavigationDatas.Vertices[_triangle.Vertices[2]],
                                                       _position);

            return(_barycentric.IsInside);
        }
コード例 #2
0
        public void PolyomnialFitsAtSamplePoints()
        {
            IInterpolation it = Barycentric.InterpolateRationalFloaterHormann(_t, _y);

            for (int i = 0; i < _y.Length; i++)
            {
                Assert.AreEqual(_y[i], it.Interpolate(_t[i]), "A Exact Point " + i);
            }
        }
コード例 #3
0
        public void PlantPatch(Barycentric bary, int BladeCount = 4096, double Area = 1.1, double MaxHeight = 1)
        {
            double sq2 = Math.Sqrt(BladeCount);

            Matrix4d TreeRotation = Matrix4d.CreateFromQuaternion(Globals.LocalUpRotation());
            Matrix4d TreePosition;
            Matrix4  final;
            Matrix4d TreeScale;
            Vector3d PlantingPos = new Vector3d();

            int bposx = (int)(Tile.x_res * (1 - bary.u));
            int bposz = (int)(Tile.z_res * (bary.v));

            // Tile.Biome.SetPixel(bposx, bposz, new float[] { 0, 1, 0, 1 });
            for (int x = (int)-sq2; x < sq2; x++)
            {
                for (int z = (int)-sq2; z < sq2; z++)
                {
                    bposx = (int)(Tile.x_res * (1 - bary.u)) - x;
                    bposz = (int)(Tile.z_res * (bary.v)) - z;

                    int t = Tile._biome.GetBiomeAt(bposx, bposz);
                    if ((t != MBiome.GRASS) &&
                        (t != MBiome.TREES) &&
                        (t != MBiome.TREES2) &&
                        (t != MBiome.WATER))
                    {
                        continue;
                    }


                    PlantingPos.X = (int)(Tile.x_res * (1 - bary.u)) - x * 0.05 * Area;
                    PlantingPos.Y = 0;
                    PlantingPos.Z = (int)(Tile.z_res * (bary.v)) - z * 0.05 * Area;

                    double yv =
                        (MPerlin.Noise(PlantingPos.X, PlantingPos.Z) * 0.4)
                        + (MPerlin.Noise(PlantingPos.X * 1.1, PlantingPos.Z * 1.1) * 0.4)
                    ;
                    //if (yv < 0.01) continue;

                    TreeScale = Matrix4d.Scale(0.05 + 0.06 * yv, 0.01 + Math.Abs(yv) * 0.15 * MaxHeight, 0.05 + 0.06 * yv);

                    PlantingPos.X += MPerlin.Noise(PlantingPos.X * 4.0, 0, PlantingPos.Z * 2.0) * 1.1;
                    PlantingPos.Z += MPerlin.Noise(PlantingPos.X * 4.0, 0, PlantingPos.Z * 2.0) * 1.1;
                    PlantingPos    = Tile.GetInterpolatedPointOnSurfaceFromGrid2(PlantingPos);

                    TreePosition = Matrix4d.CreateTranslation(PlantingPos);
                    final        = MTransform.GetFloatMatrix(TreeScale * TreeRotation * TreePosition);
                    if (TotalInstances < Settings.MaxGrassPerTerrain)
                    {
                        mats[TotalInstances] = final;
                        TotalInstances++;
                    }
                }
            }
        }
コード例 #4
0
        public void FitsAtSamplePoints()
        {
            IInterpolation it = Barycentric.InterpolatePolynomialEquidistant(Tmin, Tmax, _y);

            for (int i = 0; i < _y.Length; i++)
            {
                Assert.AreEqual(_y[i], it.Interpolate(i), "A Exact Point " + i);
            }
        }
コード例 #5
0
        private static Mesh PrepareMesh(GameObject go, Component c, Mesh mesh)
        {
            Undo.RecordObject(c, "Wireframe.PrepareMesh");
            Mesh duplicate = Object.Instantiate(mesh);

            duplicate.name = mesh.name;
            Barycentric.CalculateBarycentric(duplicate);
            EditorUtility.SetDirty(go);
            return(duplicate);
        }
コード例 #6
0
        public void SupportsLinearCase(int samples)
        {
            double[] x, y, xtest, ytest;
            LinearInterpolationCase.Build(out x, out y, out xtest, out ytest, samples);
            IInterpolation it = Barycentric.InterpolateRationalFloaterHormann(x, y);

            for (int i = 0; i < xtest.Length; i++)
            {
                Assert.AreEqual(ytest[i], it.Interpolate(xtest[i]), 1e-14, "Linear with {0} samples, sample {1}", samples, i);
            }
        }
コード例 #7
0
    private int assignObjects(
        Mesh mesh3d,
        List <DynamicObject> objects,
        Vector2 u1,
        Vector2 u2,
        Vector2 u3,
        int i,
        bool lookAtAllObjects = true)
    {
        int found = 0;

        foreach (DynamicObject obj in objects)
        {
            if (obj.assigned)
            {
                continue;
            }

            Vector2     point = obj.toVector2();
            Barycentric a     = new Barycentric(u1, u2, u3, point);
            if (a.IsInside)
            {
                //if (a.u == 0 || a.v == 0 || a.w == 0 || a.u == 1 || a.v == 1) {
                //    if (u1 == point || u2 == point || u3 == point || point.x == 0.5 || point.y == 0.5) { } else
                //        Debug.Log("Found object (" + u1.x + ", " + u1.y + " / "
                //            + u2.x + ", " + u2.y + " / "
                //            + u3.x + ", " + u3.y + " - "
                //            + point.x + ", " + point.y + ")");
                //}
                obj.barycentric = a;
                obj.assigned    = true;

                if (textureObjectsOnTriangles[i / 3] == null)
                {
                    textureObjectsOnTriangles[i / 3] = new List <DynamicObject>();
                }
                textureObjectsOnTriangles[i / 3].Add(obj);
                found++;

                if (lookAtAllObjects && neighbours[i / 3] == null)
                {
                    neighbours[i / 3] = new NeighbourCreator(mesh3d, i, neighbourRadius).create();
                }
            }
        }

        return(found);
    }
コード例 #8
0
    public Vector3 GetPixelWorldPos(Texture2D mainTex, Color32 color, int index)
    {
        int w = mainTex.width;
        int h = mainTex.height;

        // find color in texture

        /*
         * Color[] colors = mainTex.GetPixels();
         * int index = -1;
         * for (int i = 0; i < colors.Length; i++)
         * {
         *  if (colors[i] == color)
         *  {
         *      index = i;
         *      break;
         *  }
         * }
         */
        if (index == -1)
        {
            return(Vector3.zero);
        }

        // Find triangle and get local pos
        var point = new Vector2(index % w, index / w) - new Vector2(0.5f / w, 0.5f / h);
        var mf    = gameObject.GetComponent <MeshFilter>();
        var mesh  = m_mesh;
        var uvs   = m_uvs.ToArray();
        var verts = mesh.vertices;
        var tris  = mesh.triangles;

        for (int i = 0; i < m_triangles.Length; i += 3)
        {
            var uv0  = m_uvs[i + 0];
            var uv1  = m_uvs[i + 1];
            var uv2  = m_uvs[i + 2];
            var bary = new Barycentric(uv0, uv1, uv2, point);

            if (bary.IsInside)
            {
                Vector3 localPos = m_vertices[i + 0] * bary.u + m_vertices[i + 1] * bary.v + m_vertices[i + 2] * bary.w;
                // Transform to world pos and return
                return(gameObject.transform.TransformPoint(localPos));
            }
        }
        return(Vector3.zero);
    }
コード例 #9
0
ファイル: MGrass.cs プロジェクト: zenithlee/OpenWorld
        //TODO: pull the nearest blades from the Grassmats and add to mats
        //OR: Rolling buffer, taking from behind and adding edges of direction of travel
        public void PlantGrass3(MAstroBody planet, MTerrainTile tile)
        {
            Tile = tile;
            if (tile.material == null)
            {
                return;
            }
            if (Tile.GrassPlanter.IsComplete == false)
            {
                return;
            }

            Vector3d    AP   = Globals.Avatar.GetPosition();
            Barycentric bary = new Barycentric(Tile.Boundary.TL, Tile.Boundary.BR, Tile.Boundary.TR, AP);

            Vector3d Centroid = new Vector3d((1 - bary.u) * MGrassPlanter.LOD0Size, 0, bary.v * MGrassPlanter.LOD0Size);

            int cx = (int)(bary.u * MGrassPlanter.LOD0Size);
            int cz = (int)(bary.v * MGrassPlanter.LOD0Size);

            float numxinterps = MGrassPlanter.LOD0Size / Tile.x_res;
            float numzinterps = MGrassPlanter.LOD0Size / Tile.z_res;

            TotalInstances = 0;
            for (int x = 0; x < 100; x++)
            {
                for (int z = 0; z < 100; z++)
                {
                    if (TotalInstances >= Settings.MaxGrassPerTerrain)
                    {
                        continue;
                    }
                    if (cx + x > MGrassPlanter.LOD0Size)
                    {
                        continue;
                    }
                    if (cz + z > MGrassPlanter.LOD0Size)
                    {
                        continue;
                    }

                    mats[TotalInstances] = Tile.GrassPlanter.Grassmats[cx + x, cz + z];
                    TotalInstances++;
                }
            }

            Planted = true;
        }
コード例 #10
0
        public void RationalFitsAtSamplePoints()
        {
            var t = new double[40];
            var x = new double[40];

            const double Step = 10.0 / 39.0;

            for (int i = 0; i < t.Length; i++)
            {
                double tt = -5 + (i * Step);
                t[i] = tt;
                x[i] = 1.0 / (1.0 + (tt * tt));
            }

            IInterpolation it = Barycentric.InterpolateRationalFloaterHormann(t, x);

            for (int i = 0; i < x.Length; i++)
            {
                Assert.AreEqual(x[i], it.Interpolate(t[i]), "A Exact Point " + i);
            }
        }
コード例 #11
0
    /// <summary>
    /// Fill a triangle area on the texture, lerping vertex colors.
    /// </summary>
    ///
    private static void FillInTextureTriangle(Texture2D tex,
                                              Vector2 coord_a, Vector2 coord_b, Vector2 coord_c,
                                              Color color_a, Color color_b, Color color_c)
    {
        int xmin = Mathf.RoundToInt(Mathf.Min(coord_a.x, coord_b.x, coord_c.x));
        int xmax = Mathf.RoundToInt(Mathf.Max(coord_a.x, coord_b.x, coord_c.x));
        int ymin = Mathf.RoundToInt(Mathf.Min(coord_a.y, coord_b.y, coord_c.y));
        int ymax = Mathf.RoundToInt(Mathf.Max(coord_a.y, coord_b.y, coord_c.y));

        Color color = Color.clear;

        for (int x = xmin; x <= xmax; x++)
        {
            for (int y = ymin; y <= ymax; y++)
            {
                var baryCoord = new Barycentric(coord_a, coord_b, coord_c, new Vector2(x, y));
                if (baryCoord.IsInside)
                {
                    color = baryCoord.Interpolate(color_a, color_b, color_c);
                    tex.SetPixel(x, y, color);
                }
            }
        }
    }
コード例 #12
0
    private void FillInTextureTriangle(Texture2D tex,
                                       Vector2 ta, Vector2 tb, Vector2 tc,
                                       Color ca, Color cb, Color cc)
    {
        int xmin = Mathf.RoundToInt(Mathf.Min(ta.x, tb.x, tc.x));
        int xmax = Mathf.RoundToInt(Mathf.Max(ta.x, tb.x, tc.x));
        int ymin = Mathf.RoundToInt(Mathf.Min(ta.y, tb.y, tc.y));
        int ymax = Mathf.RoundToInt(Mathf.Max(ta.y, tb.y, tc.y));

        Color color = Color.clear;

        for (int x = xmin; x <= xmax; x++)
        {
            for (int y = ymin; y <= ymax; y++)
            {
                var baryCoord = new Barycentric(ta, tb, tc, new Vector2(x, y));
                if (baryCoord.IsInside)
                {
                    color = baryCoord.Interpolate(ca, cb, cc);
                    tex.SetPixel(x, y, color);
                }
            }
        }
    }
    void GenerateTexture()
    {
        int n = 512;

        Color[] pixels = new Color[n * n];

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (i >= j)
                {
                    Barycentric b = new Barycentric(new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1), new Vector2(i * 1f / n, j * 1f / n));
                    var         c = b.Interpolate(Color.red, Color.green, Color.blue);
                    int         k = i * n + j;
                    pixels[k] = c;
                }
            }
        }

        tex = new Texture2D(n, n);
        tex.SetPixels(pixels);
        tex.Apply();
    }
コード例 #14
0
        public void PolynomialFitsAtArbitraryPointsWithMaple(double t, double x, double maxAbsoluteError)
        {
            IInterpolation it = Barycentric.InterpolateRationalFloaterHormann(_t, _y);

            Assert.AreEqual(x, it.Interpolate(t), maxAbsoluteError, "Interpolation at {0}", t);
        }
コード例 #15
0
 public void FewSamples()
 {
     Assert.That(() => Barycentric.InterpolateRationalFloaterHormann(new double[0], new double[0]), Throws.ArgumentException);
     Assert.That(Barycentric.InterpolateRationalFloaterHormann(new[] { 1.0 }, new[] { 2.0 }).Interpolate(1.0), Is.EqualTo(2.0));
 }
コード例 #16
0
        public void PlantGrass(MAstroBody planet, MTerrainTile tile)
        {
            // if (Planted == true) return;
            //DistanceThreshold = tile.DistanceThreshold;
            Tile = tile;
            if (tile.material == null)
            {
                return;
            }
            MTexture tex = Tile.Biome;

            if (tex == null)
            {
                return;
            }

            this.transform.Position = tile.transform.Position;

            //Random ran = new Random(1234);

            Matrix4d TreeRotation = Matrix4d.CreateFromQuaternion(Globals.LocalUpRotation());

            //int i = 0;
            TotalInstances = 0;

            Vector3d AP = Globals.Avatar.GetPosition();
            // Console.WriteLine(AP);

            Barycentric bary = new Barycentric(Tile.Boundary.TL, Tile.Boundary.BR, Tile.Boundary.TR, AP);

            PlantPatch(bary, 64 * 64, 2, 0.8);
            //PlantPatch(bary, 32 * 32, 8, 0.3);

            // Console.WriteLine(bary.ToString());

            /*
             * double sq = 64 * 64;
             * double sq2 = Math.Sqrt(sq);
             *
             * Matrix4d TreePosition;
             * Matrix4 final;
             * Matrix4d TreeScale;
             * Vector3d PlantingPos = new Vector3d();
             * for (int x = (int)-sq2; x < sq2; x++)
             * for (int z = (int)-sq2; z < sq2; z++)
             * {
             *  PlantingPos.X = (int)(Tile.x_res * (1 - bary.u)) - x * 0.05;
             *  PlantingPos.Y = 0;
             *  PlantingPos.Z = (int)(Tile.z_res * (bary.v)) - z * 0.05;
             *
             *  double yv =
             *    (MPerlin.Noise(PlantingPos.X, PlantingPos.Z) * 0.4)
             + (MPerlin.Noise(PlantingPos.X * 1.1, PlantingPos.Z * 1.1) * 0.4)
             +    ;
             +  if (yv < 0.1) continue;
             +
             +  TreeScale = Matrix4d.Scale(0.03+0.04 * yv,  0.01 + yv * 0.14 , 0.03+0.04* yv);
             +
             +  PlantingPos.X += MPerlin.Noise(PlantingPos.X * 4.0, PlantingPos.Z * 4.1) * 1.1;
             +  PlantingPos.Z += MPerlin.Noise(PlantingPos.X * 3.8, PlantingPos.Z * 4.2) * 1.1;
             +  PlantingPos = Tile.GetInterpolatedPointOnSurfaceFromGrid2(PlantingPos);
             +
             +  TreePosition = Matrix4d.CreateTranslation(PlantingPos);
             +  final = MTransform.GetFloatMatrix(TreeScale * TreeRotation * TreePosition);
             +  if (i < Settings.MaxGrassPerTerrain)
             +  {
             +    mats[i] = final;
             +    i++;
             +  }
             + }
             +
             + TotalInstances = i;
             */

            for (int j = TotalInstances; j < Settings.MaxGrassPerTerrain; j++)
            {
                Matrix4 final = Matrix4.CreateTranslation(9999999999, 0, 0);
                mats[j] = final;
            }


            //Setup();
            //UploadBuffer();
            Planted = true;
        }
コード例 #17
0
ファイル: Intersector.cs プロジェクト: Bezhok/MeshSlicer
        //                   rightPoint1
        //                   |\
        //                   | \
        // intersectionPoint2|__\ intersectionPoint1
        //                   |   \
        //        leftPoint2 |____\ leftPoint1
        //
        public void CreateTrianglesTwoPointsOnLeft(Vector3 leftPoint1, Vector3 leftPoint2, Vector3 rightPoint1, int i,
                                                   int n0, int n1, int n2)
        {
            var n = _verts.Count;
            var intersectionPoint1 = IntersectionPlaneLinePoint(leftPoint1, rightPoint1, _planePoint, _planeNormal);
            var intersectionPoint2 = IntersectionPlaneLinePoint(leftPoint2, rightPoint1, _planePoint, _planeNormal);

            var localLeftPoint1 = _srcObject.transform.InverseTransformPoint(leftPoint1);
            var localLeftPoint2 = _srcObject.transform.InverseTransformPoint(leftPoint2);

            var localIntersectionPoint1 = _srcObject.transform.InverseTransformPoint(intersectionPoint1);
            var localIntersectionPoint2 = _srcObject.transform.InverseTransformPoint(intersectionPoint2);

            _wholeSlicePlane.AddSlicePlanePoints(localIntersectionPoint1, localIntersectionPoint2);

            int t0 = _triangles2[i + n0];
            int t1 = _triangles2[i + n1];
            int t2 = _triangles2[i + n2];
            var localRightPoint1 = _srcObject.transform.InverseTransformPoint(rightPoint1);

            if (_tangents.Any())
            {
                AddTangents(_tangents[t0], _tangents[t1], _tangents[t2], _tangents[t2]);
            }

            if (_uvs.Any())
            {
                var b1 = new Barycentric(localLeftPoint1, localLeftPoint2, localRightPoint1, localIntersectionPoint1);
                var intersectionPoint1Uv = b1.Interpolate(_uvs[t0],
                                                          _uvs[t1],
                                                          _uvs[t2]);

                var b2 = new Barycentric(localLeftPoint1, localLeftPoint2, localRightPoint1, localIntersectionPoint2);
                var intersectionPoint2Uv = b2.Interpolate(_uvs[t0],
                                                          _uvs[t1],
                                                          _uvs[t2]);

                AddUVs(_uvs[t0],
                       _uvs[t1],
                       intersectionPoint1Uv,
                       intersectionPoint2Uv);
            }

            var b3 = new Barycentric(localLeftPoint1, localLeftPoint2, localRightPoint1, localIntersectionPoint1);
            var localIntersectionPoint1Normal = b3.Interpolate(_normals[t0],
                                                               _normals[t1],
                                                               _normals[t2]);

            var b4 = new Barycentric(localLeftPoint1, localLeftPoint2, localRightPoint1, localIntersectionPoint2);
            var localIntersectionPoint2Normal = b4.Interpolate(_normals[t0],
                                                               _normals[t1],
                                                               _normals[t2]);

            AddNormals(_normals[t0],
                       _normals[t1],
                       localIntersectionPoint1Normal,
                       localIntersectionPoint2Normal);

            AddVerts(localLeftPoint1,
                     localLeftPoint2,
                     localIntersectionPoint1,
                     localIntersectionPoint2);


            if (n0 == 0 && n1 == 2)
            {
                AddTriangle(n, 1, 0, 2);
                AddTriangle(n, 1, 2, 3);
            }
            else //if (n0 == 1)
            {
                AddTriangle(n, 0, 1, 3);
                AddTriangle(n, 0, 3, 2);
            }
        }
コード例 #18
0
ファイル: TDS_NavMeshManager.cs プロジェクト: sebizart/TDShow
    /// <summary>
    /// Return if the position is inside of the triangle
    /// </summary>
    /// <param name="_position"></param>
    /// <returns></returns>
    bool IsInTriangle(Vector3 _position, TDS_Triangle _triangle)
    {
        Barycentric _barycentric = new Barycentric(navPoints[_triangle.VerticesIndex[0]].Position, navPoints[_triangle.VerticesIndex[1]].Position, navPoints[_triangle.VerticesIndex[2]].Position, _position);

        return(_barycentric.IsInside);
    }
コード例 #19
0
 /// <summary>
 /// Create a Floater-Hormann rational pole-free interpolation based on arbitrary points.
 /// </summary>
 /// <param name="points">The sample points t.</param>
 /// <param name="values">The sample point values x(t).</param>
 /// <returns>
 /// An interpolation scheme optimized for the given sample points and values,
 /// which can then be used to compute interpolations and extrapolations
 /// on arbitrary points.
 /// </returns>
 /// <remarks>
 /// if your data is already sorted in arrays, consider to use
 /// MathNet.Numerics.Interpolation.Barycentric.InterpolateRationalFloaterHormannSorted
 /// instead, which is more efficient.
 /// </remarks>
 public static IInterpolation RationalWithoutPoles(IEnumerable <double> points, IEnumerable <double> values)
 {
     return(Barycentric.InterpolateRationalFloaterHormann(points, values));
 }
コード例 #20
0
 /// <summary>
 /// Create a barycentric polynomial interpolation where the given sample points are equidistant.
 /// </summary>
 /// <param name="points">The sample points t, must be equidistant.</param>
 /// <param name="values">The sample point values x(t).</param>
 /// <returns>
 /// An interpolation scheme optimized for the given sample points and values,
 /// which can then be used to compute interpolations and extrapolations
 /// on arbitrary points.
 /// </returns>
 /// <remarks>
 /// if your data is already sorted in arrays, consider to use
 /// MathNet.Numerics.Interpolation.Barycentric.InterpolatePolynomialEquidistantSorted
 /// instead, which is more efficient.
 /// </remarks>
 public static IInterpolation PolynomialEquidistant(IEnumerable <double> points, IEnumerable <double> values)
 {
     return(Barycentric.InterpolatePolynomialEquidistant(points, values));
 }
コード例 #21
0
    /// <summary>
    /// Return if the position is inside of the triangle
    /// </summary>
    /// <param name="_position"></param>
    /// <returns></returns>
    public static bool IsInTriangle(Vector3 _position, Triangle _triangle)
    {
        Barycentric _barycentric = new Barycentric(_triangle.Vertices[0].Position, _triangle.Vertices[1].Position, _triangle.Vertices[2].Position, _position);

        return(_barycentric.IsInside);
    }
コード例 #22
0
 public void FewSamples()
 {
     Assert.That(() => Barycentric.InterpolatePolynomialEquidistant(new double[0], new double[0]), Throws.ArgumentException);
     Assert.That(Barycentric.InterpolatePolynomialEquidistant(new[] { 1.0 }, new[] { 2.0 }).Interpolate(1.0), Is.EqualTo(2.0));
 }
コード例 #23
0
        public void FitsAtArbitraryPoints(double t, double x, double maxAbsoluteError)
        {
            IInterpolation it = Barycentric.InterpolatePolynomialEquidistant(Tmin, Tmax, _y);

            Assert.AreEqual(x, it.Interpolate(t), maxAbsoluteError, "Interpolation at {0}", t);
        }
コード例 #24
0
        // Utility functions
        public bool IsPointInTriangle(Vector2 p, Vector2 a, Vector2 b, Vector2 c)
        {
            Barycentric s = new Barycentric(p, a, b, c);

            return(s.u >= 0f && s.v >= 0f && s.w >= 0f);
        }
コード例 #25
0
        internal bool TryAddBlends(SurfaceData sd, Mesh mesh, int submeshID, Vector3 point, int triangleID, out float totalWeight)
        {
            totalWeight = 0;

            //Finds Barycentric
            var triangle = triangleID * 3;
            var t0       = triangles[triangle + 0];
            var t1       = triangles[triangle + 1];
            var t2       = triangles[triangle + 2];
            var a        = vertices[t0];
            var b        = vertices[t1];
            var c        = vertices[t2];

            point = transform.InverseTransformPoint(point);
            var bary = new Barycentric(a, b, c, point);

#if UNITY_EDITOR
            lastSampledColors.Clear();
#endif

            float totalTotalWeight = 0;
            for (int i = 0; i < blendMaps.Length; i++)
            {
                var bm = blendMaps[i];
                bm.sampled = false;

                for (int ii = 0; ii < bm.subMaterials.Length; ii++)
                {
                    if (bm.subMaterials[ii].materialID == submeshID)
                    {
                        var uv = bary.Interpolate(bm.uvs[t0], bm.uvs[t1], bm.uvs[t2]);
                        uv = uv * new Vector2(bm.uvScaleOffset.x, bm.uvScaleOffset.y) + new Vector2(bm.uvScaleOffset.z, bm.uvScaleOffset.w); //?

                        Color color = bm.map.GetPixelBilinear(uv.x, uv.y);                                                                   //this only works for clamp or repeat btw (not mirror etc.)
                        bm.sampledColor = color;

                        void SampleColor(BlendMap.SurfaceBlends2 sb2)
                        {
                            if (sb2.colorMap != null)
                            {
                                sb2.sampledColor = sb2.colorMap.GetPixelBilinear(uv.x, uv.y);
                            }
                            else
                            {
                                sb2.sampledColor = Color.white;
                            }
                        }

                        SampleColor(bm.r);
                        SampleColor(bm.g);
                        SampleColor(bm.b);
                        SampleColor(bm.a);

                        totalTotalWeight += bm.weight * (color.r + color.g + color.b + color.a);

#if UNITY_EDITOR
                        lastSampledColors.Add(color);
#endif

                        bm.sampled = true;
                        break;
                    }
                }
            }

            if (totalTotalWeight > 0)
            {
                float invTotalTotal = 1f / totalTotalWeight;

                for (int i = 0; i < blendMaps.Length; i++)
                {
                    var bm = blendMaps[i];

                    if (bm.sampled)
                    {
                        float invTotal = bm.weight * invTotalTotal;

                        var color = bm.sampledColor;
                        Add(sd, bm.r.result, bm.r.sampledColor, color.r * invTotal, ref totalWeight);
                        Add(sd, bm.g.result, bm.g.sampledColor, color.g * invTotal, ref totalWeight);
                        Add(sd, bm.b.result, bm.b.sampledColor, color.b * invTotal, ref totalWeight);
                        Add(sd, bm.a.result, bm.a.sampledColor, color.a * invTotal, ref totalWeight);
                    }
                }

                return(true);
            }

            return(false);
        }