示例#1
0
        /**
         * Fill up Grid GridPoints using TriangleList input - Grid information should have been set by SetGridInfo
         *
         * @param	SamplePoints		: Sample Point List
         * @param	TriangleList		: List of triangles
         */
        public void GenerateGridElements(List <BSPoint> SamplePoints, List <BSTriangle> TriangleList)
        {
            if (!(NumGridDivisions.X > 0 && NumGridDivisions.Y > 0))
            {
                return;
            }
            //if(!(GridDimensions.IsValid))

            int TotalNumGridPoints = (int)(NumGridPointsForAxis.X * NumGridPointsForAxis.Y);

            GridPoints.Clear();


            if (SamplePoints.Count == 0 || TriangleList.Count == 0)
            {
                return;
            }

            for (int i = 0; i < TotalNumGridPoints; ++i)
            {
                GridPoints.Add(new GridElement());
            }
            Vector3 GridPointPosition;

            for (int GridPositionX = 0; GridPositionX < NumGridPointsForAxis.X; ++GridPositionX)
            {
                for (int GridPositionY = 0; GridPositionY < NumGridPointsForAxis.Y; ++GridPositionY)
                {
                    BSTriangle  SelectedTriangle = null;
                    GridElement GridPoint        = GridPoints[GridPositionX * (int)NumGridPointsForAxis.Y + GridPositionY];

                    GridPointPosition = GetPosFromIndex(GridPositionX, GridPositionY);

                    Vector3 Weights = Vector3.Zero;
                    if (FindTriangleThisPointBelongsTo(GridPointPosition, ref Weights, ref SelectedTriangle, TriangleList))
                    {
                        // found it
                        GridPoint.Weights[0] = Weights.X;
                        GridPoint.Weights[1] = Weights.Y;
                        GridPoint.Weights[2] = Weights.Z;
                        // need to find sample point index
                        // @todo fix this with better solution
                        // lazy me
                        GridPoint.Indices[0] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[0]); });
                        GridPoint.Indices[1] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[1]); });
                        GridPoint.Indices[2] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[2]); });

                        //check(GridPoint.Indices[0] != INDEX_NONE);
                        //check(GridPoint.Indices[1] != INDEX_NONE);
                        //check(GridPoint.Indices[2] != INDEX_NONE);
                    }
                    else
                    {
                        List <BSSortByDistance> SortedTriangles = new List <BSSortByDistance>();
                        for (int TriangleIndex = 0; TriangleIndex < TriangleList.Count; ++TriangleIndex)
                        {
                            // Check if points are collinear
                            BSTriangle Triangle = TriangleList[TriangleIndex];
                            Vector3    EdgeA    = Triangle.Vertices[1].Position - Triangle.Vertices[0].Position;
                            Vector3    EdgeB    = Triangle.Vertices[2].Position - Triangle.Vertices[0].Position;
                            float      Result   = EdgeA.X * EdgeB.Y - EdgeA.Y * EdgeB.X;
                            // Only add valid triangles
                            if (Result > 0.0f)
                            {
                                SortedTriangles.Add(new BSSortByDistance(TriangleIndex, Triangle.GetDistance(GridPointPosition)));
                            }
                        }

                        if (SortedTriangles.Count > 0)
                        {
                            // SortedTriangles.Sort([](FSortByDistance A, FSortByDistance B) { return A.Distance < B.Distance; });
                            BSTriangle ClosestTriangle = TriangleList[SortedTriangles[0].Index];

                            // For the closest triangle, determine which of its edges is closest to the grid point
                            List <BSSortByDistance> Edges         = new List <BSSortByDistance>();
                            List <Vector3>          PointsOnEdges = new List <Vector3>();
                            for (int EdgeIndex = 0; EdgeIndex < 3; ++EdgeIndex)
                            {
                                Vector3 ClosestPoint = ClosestPointOnLine(ClosestTriangle.Edges[EdgeIndex].Vertices[0].Position, ClosestTriangle.Edges[EdgeIndex].Vertices[1].Position, GridPointPosition);
                                Edges.Add(new BSSortByDistance(EdgeIndex, (ClosestPoint - GridPointPosition).LengthSquared()));
                                PointsOnEdges.Add(ClosestPoint);
                            }
                            //Edges.Sort([](FSortByDistance A, FSortByDistance B) { return A.Distance < B.Distance; });

                            // Calculate weighting using the closest edge points and the clamped grid position on the line
                            Vector3 GridWeights = GetBaryCentric2D(PointsOnEdges[Edges[0].Index], ClosestTriangle.Vertices[0].Position, ClosestTriangle.Vertices[1].Position, ClosestTriangle.Vertices[2].Position);

                            for (int Index = 0; Index < 3; ++Index)
                            {
                                GridPoint.Weights[Index] = GridWeights[Index];
                                GridPoint.Indices[Index] = SamplePoints.FindIndex((point) => { return(point == ClosestTriangle.Vertices[Index]); });
                            }
                        }
                        else
                        {
                            // This means that there is either one point, two points or collinear triangles on the grid
                            if (SamplePoints.Count == 1)
                            {
                                // Just one, fill all grid points to the single sample
                                GridPoint.Weights[0] = 1.0f;
                                GridPoint.Indices[0] = 0;
                            }
                            else
                            {
                                // Two points or co-linear triangles, first find the two closest samples
                                List <BSSortByDistance> SampleDistances = new List <BSSortByDistance>();
                                for (int PointIndex = 0; PointIndex < SamplePoints.Count; ++PointIndex)
                                {
                                    var     vec     = (SamplePoints[PointIndex].Position - GridPointPosition);
                                    Vector2 vector2 = new Vector2(vec.X, vec.Y);
                                    float   DistanceFromSampleToPoint = vector2.LengthSquared();
                                    SampleDistances.Add(new BSSortByDistance(PointIndex, DistanceFromSampleToPoint));
                                }
                                SampleDistances.Sort((A, B) =>
                                {
                                    if (A.Distance == B.Distance)
                                    {
                                        return(0);
                                    }
                                    return(A.Distance > B.Distance ? 1 : -1);
                                });

                                // Find closest point on line between the two samples (clamping the grid position to the line, just like clamping to the triangle edges)
                                BSPoint[] Samples = new BSPoint[2];
                                Samples[0] = SamplePoints[SampleDistances[0].Index];
                                Samples[1] = SamplePoints[SampleDistances[1].Index];
                                Vector3 ClosestPointOnTheLine = ClosestPointOnLine(Samples[0].Position, Samples[1].Position, GridPointPosition);

                                var     temp        = (Samples[0].Position - Samples[1].Position);
                                Vector2 tempVector2 = new Vector2(temp.X, temp.Y);
                                float   LineLength  = tempVector2.LengthSquared();

                                // Weight the samples according to the distance from the grid point on the line to the samples
                                for (int SampleIndex = 0; SampleIndex < 2; ++SampleIndex)
                                {
                                    var thelength3D = (Samples[SampleIndex].Position - ClosestPointOnTheLine);
                                    var thelength2D = new Vector2(thelength3D.X, thelength3D.Y);
                                    GridPoint.Weights[SampleIndex] = (LineLength - thelength2D.LengthSquared()) / LineLength;
                                    GridPoint.Indices[SampleIndex] = SamplePoints.FindIndex((point) => { return(point == Samples[SampleIndex]); });
                                }
                            }
                        }
                    }
                }
            }
        }