Exemple #1
0
        private IEnumerator PunchOutStep1(XZPolygon polygon)
        {
            Profiler.BeginSample("PunchOutStep1");

            float fTimeWhenStartedChunk = Time.realtimeSinceStartup;

            maVerticesUnderPolygonPoints = new Vertex[polygon.maPoints.Length - 1];

            // (1) For each polygon point, determine which triangle it's in, and split that triangle into three such that the point is on a new vertex
            for (int p = 0; p < polygon.maPoints.Length - 1; p++)  //Length-1 because it's a closed polyline
            {
                // Coroutine time management
                if (Time.realtimeSinceStartup - fTimeWhenStartedChunk > MAX_TIME_CHUNK)
                {
                    // Enough done this frame, go on holiday
                    yield return(null);

                    // Back from holyday
                    fTimeWhenStartedChunk = Time.realtimeSinceStartup;
                }



                Vector3 vPoint = polygon.maPoints[p];

                if (p > 0 && (vPoint - polygon.maPoints[p - 1]).magnitude < 0.0001f)
                {
                    Debug.Log("Polygon has two very near points. Distance is " + (vPoint - polygon.maPoints[p - 1]).magnitude);
                }

                if (p > 0)
                {
                    // Debug.DrawLine(polygon.maPoints[p - 1], polygon.maPoints[p], Color.yellow, 1000.0f);
                }

                for (int t = 0; t < mlTriangles.Count; t++)
                {
                    Triangle triangle = mlTriangles[t];

                    Vertex P = null;
                    Vertex Q = null;
                    if (triangle.IsFarFromXZ(vPoint))
                    {
                        // NOP - Continue
                    }
                    else if (triangle.mA.IsUnder(vPoint) || triangle.mB.IsUnder(vPoint) || triangle.mC.IsUnder(vPoint))
                    {
                        // We are already over a vertex, yay
                        if (triangle.mA.IsUnder(vPoint))
                        {
                            maVerticesUnderPolygonPoints[p] = triangle.mA;
                            // Debug.DrawLine(triangle.mA.mvPos - 0.01f * Vector3.up, triangle.mA.mvPos + 0.01f * Vector3.up, Color.grey, 1000.0f);
                        }
                        else if (triangle.mB.IsUnder(vPoint))
                        {
                            maVerticesUnderPolygonPoints[p] = triangle.mB;
                            // Debug.DrawLine(triangle.mB.mvPos - 0.01f * Vector3.up, triangle.mB.mvPos + 0.01f * Vector3.up, Color.grey, 1000.0f);
                        }
                        else if (triangle.mC.IsUnder(vPoint))
                        {
                            maVerticesUnderPolygonPoints[p] = triangle.mC;
                            // Debug.DrawLine(triangle.mC.mvPos - 0.01f * Vector3.up, triangle.mC.mvPos + 0.01f * Vector3.up, Color.grey, 1000.0f);
                        }
                        break;
                    }
                    else if (triangle.BorderContainsXZ(vPoint, out P, out Q))
                    {
                        // We are on an edge
                        //             P---------------R
                        //           /  \ triangleBis//
                        //         /     \         / /
                        //       /        \     /   /
                        //     / triangle  \  /    /
                        //   S -_- - - - - -X     /
                        //        -  _       \   /
                        //              -  _  \ /
                        //                   - Q
                        //

                        //Debug.Log ("p="+p+": Splitting edge");

                        // Compute where X is
                        Vector3 vPQ = Q.mvPos - P.mvPos;
                        vPQ.y = 0.0f;
                        Vector3 vPX = vPoint - P.mvPos;
                        vPX.y = 0.0f;
                        float fCutRatio = vPX.magnitude / vPQ.magnitude;

                        // Add new vertex
                        Vertex X = AddVertex(Vector3.Lerp(P.mvPos, Q.mvPos, fCutRatio));
#if UNITY_EDITOR
                        X.DEBUG_INFO = "added on edge in step1";
#endif
                        maVerticesUnderPolygonPoints[p] = X;

                        // Debug.DrawLine(X.mvPos - 0.01f * Vector3.up, X.mvPos + 0.01f * Vector3.up, Color.white, 1000.0f);

                        // Interpolate UV coordinates
                        X.mvUV = Vector2.Lerp(P.mvUV, Q.mvUV, fCutRatio);

                        //Get the point S
                        Vertex S = triangle.GetThirdCorner(P, Q);

                        // Before we kill triangle, check if there's a second triangle to subdivide
                        Triangle triangleBis = triangle.GetNeighbourTriangleBehind(P, Q);

                        // Supdivide triangle
                        RemoveTriangle(t);
                        bool bFlip = (Vector3.Cross(P.mvPos - S.mvPos, Q.mvPos - S.mvPos).y > 0);
                        AddTriangle(S, X, P, bFlip);
                        AddTriangle(S, Q, X, bFlip);

                        if (triangleBis != null)
                        {
                            Vertex R = triangleBis.GetThirdCorner(P, Q);
                            RemoveTriangle(triangleBis);
                            AddTriangle(P, X, R, bFlip);
                            AddTriangle(X, Q, R, bFlip);
                        }
                        break;
                    }
                    else if (triangle.ContainsXZ(vPoint))
                    {
                        //Debug.Log ("p="+p+": Splitting triangle");

                        // We have found the triangle
                        //               B
                        //              / \
                        //            /  | \
                        //          /   |   \
                        //        /    |     \ 
                        //      /    _ P' _   \ 
                        //    /_ - -       -  _\ 
                        //  A-------------------C

                        // Retrieve the existing vertices
                        Vertex A = triangle.mA;
                        Vertex B = triangle.mB;
                        Vertex C = triangle.mC;

                        // We want to project P vertically (not orthogonally) onto a point P' on the ABC plane.
                        // The problem is choosing the right altitude.
                        // If we set U = P-A, V = C-A, W = B-A, we are looking for lambda, my, such that P' = A + lambda V + my W has the same x and z coordinates as P.
                        // This comes back to resolving the linear equation system
                        //
                        //   lambda V.x + my * W.x == U.x
                        //   lambda V.z + my * W.z == U.z  , or in matrix form
                        //
                        //   [V.x   W.x]   ( lambda )   ( U.x )
                        //   [V.z   W.z] * (   my   ) = ( U.z )
                        //
                        //   We resolve for the vector on the left:
                        //
                        //    ( lambda )    [V.x   W.x]-1   ( U.x )           [ W.z  -W.x]   ( U.x )
                        //    (   my   ) =  [V.z   W.z]   * ( U.z ) = 1/det * [-V.z   V.x] * ( U.z )
                        //
                        // So all we have to do is invert a 2x2 matrix. That should not be a problem.

                        // Initialize U, V, W
                        Vector3 vU = vPoint - A.mvPos;
                        Vector3 vV = C.mvPos - A.mvPos;
                        Vector3 vW = B.mvPos - A.mvPos;

                        // Compute the determinant
                        float fDet = vV.x * vW.z - vV.z * vW.x;
                        if (fDet == 0.0f)
                        {
                            // Degenerated triangle
                            Debug.LogError("Degenerated triangle");
                            continue;
                        }

                        // Resolve for lambda and my
                        float fLambda = (1.0f / fDet) * (vW.z * vU.x - vW.x * vU.z);
                        float fMy     = (1.0f / fDet) * (-vV.z * vU.x + vV.x * vU.z);

                        // Now we can apply lambda and my
                        Vector3 vPprime = A.mvPos + fLambda * vV + fMy * vW;

                        // Add a vertex at P'
                        Vertex newVertex = AddVertex(vPprime);
#if UNITY_EDITOR
                        newVertex.DEBUG_INFO = "added in triangle in step 1";
#endif
                        maVerticesUnderPolygonPoints[p] = newVertex;

                        // Debug.DrawLine(newVertex.mvPos - 0.01f * Vector3.up, newVertex.mvPos + 0.01f * Vector3.up, Color.black, 1000.0f);

                        // Interpolate UV coordinates
                        newVertex.mvUV = A.mvUV + fLambda * (C.mvUV - A.mvUV) + fMy * (B.mvUV - A.mvUV);

                        // Replace the triangle
                        RemoveTriangle(t);
                        AddTriangle(C, A, newVertex);
                        AddTriangle(A, B, newVertex);
                        AddTriangle(B, C, newVertex);

                        // Stop the inner loop
                        break;
                    }
                }
            }
            Profiler.EndSample();
        }