コード例 #1
0
ファイル: SplineMatrixOps.cs プロジェクト: AJ213/Awitu
        private static float GetNodeWeight(Vector3 prev, Vector3 node, Vector3 next, SerpentineFactors factors, float maxHeight)
        /// returns node candidate rating 0-infinity, lower is better
        {
            //incline
            Vector3 prevDelta     = prev - node;
            float   prevHorDist   = ((Vector2D)prevDelta).Magnitude;
            float   prevElevation = prevDelta.y > 0 ? prevDelta.y : -prevDelta.y;
            float   prevIncline   = prevElevation / prevHorDist;

            Vector3 nextDelta     = node - next;
            float   nextHorDist   = ((Vector2D)nextDelta).Magnitude;
            float   nextElevation = nextDelta.y > 0 ? nextDelta.y : -nextDelta.y;
            float   nextIncline   = nextElevation / nextHorDist;

            float inclineRating = prevIncline > nextIncline ? prevIncline : nextIncline;        //0 (planar), 1 (45 degree), to infinity (90 degree)

            inclineRating = 1 - Mathf.Atan(inclineRating) / (Mathf.PI / 2f);                    //1 (planar), 0.5 (45 degree), 0 (90 degree)
            //inclineRating *= inclineRating;

            //length
            Vector2D vec     = ((Vector2D)(prev - next)).Normalized;
            float    prevDot = Vector2D.Dot(vec, ((Vector2D)(node - prev)).Normalized);
            float    nextDot = Vector2D.Dot(vec, ((Vector2D)(node - next)).Normalized);

            float length  = ((Vector2D)(prev - next)).Magnitude;
            float nLength = ((Vector2D)(prev - node)).Magnitude + ((Vector2D)(node - next)).Magnitude;

            float lengthRating = length / nLength;                      //1 (straight), 0.7071 (90 degree), 0 (sharp corner)
            //lengthRating *= lengthRating;

            //height
            float heightRating = node.y / maxHeight;

            if (factors.height < 0)
            {
                heightRating = 1 - heightRating;
            }

            //	if (lengthFactor < 1) lengthFactor = 1; //now 1 to 2 only
            //	lengthFactor -= 1; //now 0 to 1;
            //	if (lengthFactor == 1) lengthFactor = float.MaxValue;
            //	else lengthFactor = 1 / (1-lengthFactor); //now 0 to infinity

            float rating = inclineRating * factors.incline + lengthRating * factors.length + heightRating * Mathf.Abs(factors.height);

            //Mathf.Pow(inclineRating, (1-factors.incline)) * Mathf.Pow(lengthRating, (1-factors.length));

            if (tmpIteration == tmpHighlightIteration && tmpNode == tmpHighlightNode)
            {
                DebugGizmos.DrawLabel("Serp", node,
                                      "Node:" + tmpNode + " var:" + tmpVariant +
                                      "\nInc:" + inclineRating.ToString() + "(" + prevIncline.ToString() + ", " + nextIncline.ToString() + ")" +
                                      "\nLen:" + lengthRating.ToString() +           //"(" + length + ", " + nLength + ")" +
                                      "\nSum:" + rating.ToString(),
                                      additive: true);

                DebugGizmos.DrawLine("Serp", node, prev, Color.red, additive: true);

                DebugGizmos.DrawDot("Serp", node, 6, Color.red, additive: true);
            }

            return(rating);
        }
コード例 #2
0
ファイル: SplineMatrixOps.cs プロジェクト: AJ213/Awitu
        public static void SerpentineUnordered(MatrixWorld heights, Spline spline, float segLength, int iterations, SerpentineFactors factors)
        {
            DebugGizmos.Clear("Serp");

            factors.Normalize();

            float DistFn(Vector3 n1, Vector3 n2) => Mathf.Sqrt((n1.x - n2.x) * (n1.x - n2.x) + (n1.z - n2.z) * (n1.z - n2.z));

            CoordRect rect = heights.rect;
            Coord     rectMin = heights.rect.offset; Coord rectMax = heights.rect.offset + heights.rect.size;
            float     pixelSize = heights.PixelSize.x;

            for (int i = 0; i < iterations; i++)
            {
                spline.SubdivideDist(segLength, DistFn);
                Floor(heights, spline);

                tmpIteration          = i;
                tmpHighlightIteration = iterations - 1;

                //finding node with lowest rating
                float lowestRating = float.MaxValue;
                int   lowestNum    = 0;

                for (int n = 1; n < spline.nodes.Length - 1; n++)
                {
                    float rating = GetNodeWeight(spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1], factors, heights.worldSize.y);

                    if (rating < lowestRating)
                    {
                        lowestRating = rating;
                        lowestNum    = n;
                    }
                }

                tmpNode = lowestNum;

                float   weight     = GetNodeWeight(spline.nodes[lowestNum - 1], spline.nodes[lowestNum], spline.nodes[lowestNum + 1], factors, heights.worldSize.y);
                Vector3 moveVector = GetMoveVector(heights,
                                                   spline.nodes[lowestNum - 1], spline.nodes[lowestNum], spline.nodes[lowestNum + 1],
                                                   weight, 1, heights.PixelSize.x, factors);

                spline.nodes[lowestNum] += moveVector;                        //*heights.PixelSize*0.2f;// * (2f/iterations);

                spline.Weld(segLength / 2, DistFn);
            }
        }
コード例 #3
0
ファイル: SplineMatrixOps.cs プロジェクト: AJ213/Awitu
        private static Vector3 GetMoveVector(MatrixWorld heights,
                                             Vector3 prev, Vector3 node, Vector3 next,
                                             float thisWeight, int evalCount, float evalStep, SerpentineFactors factors)
        {
            Vector3 tan  = (next - prev).normalized;
            Vector3 perp = Vector3.Cross(tan, Vector3.up);

            Vector3 minNode   = node;
            float   minWeight = thisWeight;

            float lWeights = 0;
            float rWeights = 0;

            float topLeftRating  = 0;
            float topRightRating = 0;

            for (int p = 1; p <= evalCount; p++)
            {
                Vector3 lNode = node + perp * (evalStep * p);
                lNode.y = heights.GetWorldInterpolatedValue(lNode.x, lNode.z) * heights.worldSize.y;
                float lRating = GetNodeWeight(prev, lNode, next, factors, heights.worldSize.y);
                //lWeight = lWeight*(1-(float)p/evalCount) + thisWeight*((float)p/evalCount);
                lWeights += lRating;
                if (lRating > topLeftRating)
                {
                    topLeftRating = lRating;
                }

                Vector3 rNode = node - perp * (evalStep * p);
                rNode.y = heights.GetWorldInterpolatedValue(rNode.x, rNode.z) * heights.worldSize.y;
                float rRating = GetNodeWeight(prev, rNode, next, factors, heights.worldSize.y);
                //rWeight = rWeight*(1-(float)p/evalCount) + thisWeight*((float)p/evalCount);
                rWeights += rRating;
                if (rRating > topRightRating)
                {
                    topRightRating = rRating;
                }
            }

            //return perp*(lWeights-rWeights);
            //return perp*(topLeftWeight-topRightWeight);
            if (topLeftRating > topRightRating && topLeftRating > thisWeight)
            {
                return(perp * (topLeftRating - thisWeight));
            }
            else if (topRightRating > topLeftRating && topRightRating > thisWeight)
            {
                return(-perp * (topRightRating - thisWeight));
            }
            else
            {
                return(Vector3.zero);
            }
        }
コード例 #4
0
ファイル: SplineMatrixOps.cs プロジェクト: AJ213/Awitu
        public static void Serpentine(MatrixWorld heights, Spline spline, float segLength, int iterations, SerpentineFactors factors)
        {
            DebugGizmos.Clear("Serp");

            factors.Normalize();

            float DistFn(Vector3 n1, Vector3 n2) => Mathf.Sqrt((n1.x - n2.x) * (n1.x - n2.x) + (n1.z - n2.z) * (n1.z - n2.z));

            for (int i = 0; i < iterations; i++)
            {
                tmpIteration          = i;
                tmpHighlightIteration = iterations - 1;

                spline.SubdivideDist(segLength, DistFn);
                Floor(heights, spline);


                CoordRect rect = heights.rect;
                Coord     rectMin = heights.rect.offset; Coord rectMax = heights.rect.offset + heights.rect.size;
                float     pixelSize = heights.PixelSize.x;

                Vector3[] newNodes = new Vector3[spline.nodes.Length];

                for (int n = 1; n < spline.nodes.Length - 1; n++)
                {
                    //if (n>2) { newNodes[n]=spline.nodes[n]; continue; }

                    tmpNode = n;

                    float   weight     = GetNodeWeight(spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1], factors, heights.worldSize.y);
                    Vector3 moveVector = GetMoveVector(heights,
                                                       spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1],
                                                       weight, 1, heights.PixelSize.x, factors);

                    newNodes[n] = spline.nodes[n] + moveVector * 3f;                          //*heights.PixelSize*0.2f;// * (2f/iterations);

                    if (tmpHighlightIteration == i)
                    {
                        DebugGizmos.DrawRay("Serp", newNodes[n], moveVector, Color.yellow, additive: true);
                    }
                }

                newNodes[0] = spline.nodes[0];
                newNodes[newNodes.Length - 1] = spline.nodes[spline.nodes.Length - 1];
                spline.nodes = newNodes;

                spline.Weld(segLength / 2, DistFn);
            }
        }