public void RetrieveInfos(CPNPolygon polygon)
        {
            CPNSideEdge[] polylines = polygon.sideEdges;

            int M1 = polylines[0].GetN();
            int M2 = polylines[1].GetN();
            int M3 = polylines[2].GetN();

            this.M = M3 > M1 ? M3 : M1;
            this.M = M2 > M ? M2 : M;

            this.internalsN = (((M - 1) * (M - 2)) >> 1);

            if (M == 1)
            {
                this.trianglesN = 1;
            }
            else if (M == 2)
            {
                this.trianglesN = (M1 + M2 + M3 - 2);
            }
            else
            {
                this.trianglesN = (M - 3) * (M - 3) + M1 + M2 + M3 + 3 * (M - 3);
            }

            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            // printf("\nSFCPNTrianglesMeshStructure.retrieveInfos inputs M1:%d
            // M2:%d M3:%d evaluated M:%d internalsN:%d trianglesN:%d",
            // M1,M2,M3,M,internalsN,trianglesN);
            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
        }
        public void RetrieveInfos(CPNPolygon buildingPolygonData)
        {
            this.M = 0;

            int missing = 0;

            for (int i = 0; i < sides; i++)
            {
                int N = buildingPolygonData.sideEdges[i].GetN();
                if (this.M < N)
                {
                    this.M = N;
                }
            }
            for (int i = 0; i < sides; i++)
            {
                int N = buildingPolygonData.sideEdges[i].GetN();
                missing += (M - N);
            }

            this.nInternals = 1 + sides * (((M)*(M - 1)) >> 1);

            //TODO : I think this is wrong. You miss a triangle when N is less then M, you know?
            this.nTriangles = sides * ((M * M)) - missing;
        }
        public void CreateQuadTessellation(OutputMesh builder, int internalsIndex, int facesIndex,
                                           CPNPolygon polygon)
        {
            /*---- SPECIAL CASES  ----*/
            if (DealWithSpecialCases(builder, facesIndex, polygon))
            {
                return;
            }

            CPNSideEdge[] polylines             = polygon.sideEdges;
            int           trPosition            = facesIndex;
            int           innerVerticesPosition = internalsIndex;

            //Internal Quads -- Pretty Straightforward
            for (int i = 0; i < MV - 2; i++)
            {
                int rowPosition1 = innerVerticesPosition + (i) * (MH - 1);
                int rowPosition2 = innerVerticesPosition + (i + 1) * (MH - 1);

                for (int j = 0; j < MH - 2; j++)
                {
                    trPosition = builder.WriteQuad(trPosition, rowPosition1 + j, rowPosition1 + j + 1,
                                                   rowPosition2 + j + 1, rowPosition2 + j);
                }
            }

            UpdateSides(builder, polygon, trPosition, innerVerticesPosition);
        }
        private bool DealWithSpecialCases(OutputMesh builder, int facesIndex,
                                          CPNPolygon polygon)
        {
            CPNSideEdge[] polylines = polygon.sideEdges;
            /*---- SPECIAL CASES  ----*/
            if (MV == 1 && MH != 1)
            {
                NetPolylineIndicesArray array1 = new NetPolylineIndicesArray(polylines[0], builder);
                NetPolylineIndicesArray array2 = new NetPolylineIndicesArray(polylines[2], builder, true);
                MeshStructures.CreateSideTriangles(builder, array2, array1, facesIndex);
                return(true);
            }

            if (MV != 1 && MH == 1)
            {
                NetPolylineIndicesArray array1 = new NetPolylineIndicesArray(polylines[1], builder);
                NetPolylineIndicesArray array2 = new NetPolylineIndicesArray(polylines[3], builder, true);
                MeshStructures.CreateSideTriangles(builder, array2, array1, facesIndex);
                return(true);
            }

            if (MV == 1 && MH == 1)
            {
                builder.WriteQuad(facesIndex, polylines[0].GetFirstVertex(), polylines[1].GetFirstVertex(),
                                  polylines[2].GetFirstVertex(), polylines[3].GetFirstVertex());
                return(true);
            }
            return(false);
        }
        public int UpdateSides(OutputMesh builder, CPNPolygon polygon, int trPosition,
                               int innerVerticesPosition)
        {
            CPNSideEdge[] polylines = polygon.sideEdges;

            first[0] = innerVerticesPosition;
            first[1] = innerVerticesPosition + (MH - 2);
            first[2] = innerVerticesPosition + (MV - 1) * (MH - 1) - 1;
            first[3] = innerVerticesPosition + (MV - 2) * (MH - 1);

            move[0] = 1;
            move[1] = (MH - 1);
            move[2] = -1;
            move[3] = -(MH - 1);

            count[0] = MH - 1;
            count[1] = MV - 1;
            count[2] = MH - 1;
            count[3] = MV - 1;

            for (int i = 0; i < 4; i++)
            {
                if (polylines[i].GetN() > 1)
                {
                    LinearMeshIndicesArray          lmi = new LinearMeshIndicesArray(first[i], move[i], count[i], builder);
                    NetPolylineInternalIndicesArray npi = new NetPolylineInternalIndicesArray(polylines[i], builder);
                    trPosition = MeshStructures.CreateSideTriangles(builder, lmi, npi, trPosition);
                }
                else
                {
                    LinearMeshIndicesArray  lmi = new LinearMeshIndicesArray(first[i], move[i], count[i], builder);
                    NetPolylineIndicesArray npi = new NetPolylineIndicesArray(polylines[i], builder);
                    trPosition = MeshStructures.CreateSideTriangles(builder, lmi, npi, trPosition);
                }

                int prev = i == 0 ? 3 : i - 1;
                if (polylines[i].GetN() > 1 && polylines[prev].GetN() > 1)
                {
                    trPosition = builder.WriteQuad(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1), first[i],
                                                   polylines[prev].GetBackIndex(1));
                }
                else if (polylines[i].GetN() > 1)
                {
                    trPosition = builder.WriteTriangle(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                       first[i]);
                }
                else if (polylines[prev].GetN() > 1)
                {
                    trPosition = builder.WriteTriangle(trPosition, polylines[i].GetIndex(0), first[i],
                                                       polylines[prev].GetBackIndex(1));
                }

                // System.err.println("trPosition on sides " + trPosition);
            }

            return(trPosition);
        }
        Vector3 EvalVertex(OutputMesh builder, CPNPolygon polylines, float innerX, float innerY, out Vector3 uv)
        {
            updateVals(innerX, innerY);

            for (int k = 0; k < sides; k++)
            {
                int kprev = k == 0 ? sides - 1 : k - 1;

                float dx = (innerX * cos_[k] - innerY * sin_[k]) - 1;
                float dy = (innerX * sin_[k] + innerY * cos_[k]);

                float U = cornerCoordsMatrix[0] * dx + cornerCoordsMatrix[2] * dy;
                float V = cornerCoordsMatrix[1] * dx + cornerCoordsMatrix[3] * dy;

                int indexU = (int)((U + 0.0001f) * totalInterpolationStep);
                int indexV = (int)((V + 0.0001f) * totalInterpolationStep);

                if (indexU > interpolationSteps)
                {
                    indexU = interpolationSteps;
                }
                if (indexV > interpolationSteps)
                {
                    indexV = interpolationSteps;
                }

                tmpInterpolations[k]   = evalVertex(polylines.sideEdges[k], polylines.sideEdges[kprev], U, V);
                tmpInterpolationsUV[k] = evalUV(polylines.sideEdges[k], polylines.sideEdges[kprev], U, V);
            }

            Vector3 vertex = val[0] * tmpInterpolations[0];

            uv = val[0] * tmpInterpolationsUV[0];

            for (int k = 1; k < sides; k++)
            {
                vertex = vertex + tmpInterpolations[k] * val[k];
                uv     = uv + tmpInterpolationsUV[k] * val[k];
            }

            return(vertex);
        }
        public void RetrieveInfos(CPNPolygon polygon)
        {
            CPNSideEdge[] polylines = polygon.sideEdges;

            int M1 = polylines[0].GetN();
            int M2 = polylines[1].GetN();
            int M3 = polylines[2].GetN();
            int M4 = polylines[3].GetN();

            this.MV = M4 > M2 ? M4 : M2;
            this.MH = M3 > M1 ? M3 : M1;

            this.nInternals = (MH - 1) * (MV - 1);

            if (MV == 1 && MH == 1)
            {
                this.nTriangles = 2;
            }
            else
            {
                this.nTriangles = 2 * (MH - 2) * (MV - 2) + M1 + M2 + M3 + M4 + 2 * (MH - 2) + 2 * (MV - 2);
            }
        }
Beispiel #8
0
        public void UdpdateContent(OutputMesh mesh, CPNPolygon polygon, int internalsIndex,
                                   int facesIndex, bool doUpdateStructure = true)
        {
            triangleStructure.RetrieveInfos(polygon);

            int   M    = triangleStructure.GetM();
            float step = 1.0f / M;

            CPNSideEdge[] polylines = polygon.sideEdges;
            buffer0.writeWithGuide(polylines[0], M, mesh, evaluator);
            buffer1.writeWithGuide(polylines[1], M, mesh, evaluator);
            buffer2.writeWithGuide(polylines[2], M, mesh, evaluator);

            corner0.Set(buffer0, buffer2);
            corner1.Set(buffer1, buffer0);
            corner2.Set(buffer2, buffer1);

            prepareMemory(M);

            for (int i = 1; i < M - 1; i++)
            {
                for (int j = 1; j < M - 1 - (i - 1); j++)
                {
                    int wIndex = M - i - j;

                    Vector3 V1   = corner0.evalVertex(j, i);
                    Vector3 V1uv = corner0.evalUV(j, i);

                    Vector3 V2   = corner1.evalVertex(i, wIndex);
                    Vector3 V2uv = corner1.evalUV(i, wIndex);

                    Vector3 V3   = corner2.evalVertex(wIndex, j);
                    Vector3 V3uv = corner2.evalUV(wIndex, j);

                    float U = j * step;
                    float V = i * step;
                    float W = 1 - U - V;

                    float a1 = W * W;
                    float a2 = U * U;
                    float a3 = V * V;
#if DEBUG
                    if (interpolationCorner != 0)
                    {
                        switch (interpolationCorner)
                        {
                        case 1: a1 = 1; a2 = 0; a3 = 0; break;

                        case 2: a1 = 0; a2 = 1; a3 = 0; break;

                        case 3: a1 = 0; a2 = 0; a3 = 1; break;
                        }
                    }
#endif

                    float rec = 1.0f / (a1 + a2 + a3);
                    a1 *= rec;
                    a2 *= rec;
                    a3 *= rec;

                    Vector3 vertex = V1 * a1 + V2 * a2 + V3 * a3;
                    Vector3 uv     = V1uv * a1 + V2uv * a2 + V3uv * a3;

                    int memoryIndex = j + i * (M + 1) - (((i) * (i - 1)) >> 1);
                    memory.vertices[memoryIndex] = vertex;
                    memory.uv[memoryIndex]       = uv;
                }
            }

            int position = internalsIndex;

            for (int i = 1; i < M - 1; i++)
            {
                for (int j = 1; j < M - 1 - (i - 1); j++)
                {
                    int rowIndex     = i * (M + 1) - (((i) * (i - 1)) >> 1);
                    int rowIndexPrev = (i - 1) * (M + 1) - (((i - 1) * (i - 2)) >> 1);
                    int rowIndexNext = (i + 1) * (M + 1) - (((i + 1) * (i)) >> 1);

                    int     memoryIndex = j + rowIndex;
                    Vector3 vertex      = memory.vertices[memoryIndex];
                    Vector3 uv          = memory.uv[memoryIndex];

                    //Normal (S is the vertices, the surface)
                    Vector3 dSdu   = memory.vertices[memoryIndex + 1] - memory.vertices[memoryIndex - 1];
                    Vector3 dSdv   = memory.vertices[rowIndexNext + j] - memory.vertices[rowIndexPrev + j];
                    Vector3 normal = Vector3.Cross(dSdu, dSdv).normalized;

                    //Tangent
                    Vector3 dTxdu   = memory.uv[memoryIndex + 1] - memory.uv[memoryIndex - 1];
                    Vector3 dTxdv   = memory.uv[rowIndexNext + j] - memory.uv[rowIndexPrev + j];
                    Vector3 tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);

                    mesh.SetPNUV(position, vertex, normal, uv, tangent);

                    position++;
                }
            }

            if (doUpdateStructure)
            {
                triangleStructure.CreateTriangleTessellation(mesh, internalsIndex, facesIndex, polygon);
            }
        }
Beispiel #9
0
 public void RetrieveInfos(CPNPolygon buildingPolygonData)
 {
     triangleStructure.RetrieveInfos(buildingPolygonData);
 }
        public void UdpdateContent(OutputMesh mesh, CPNPolygon polygon, int internalsIndex,
                                   int facesIndex, bool doUpdateStructure = true)
        {
            triangleStructure.RetrieveInfos(polygon);

            bool useUV           = mesh.DoUseUVs();
            bool useNormals      = mesh.DoNormals();
            bool useTangents     = mesh.DoUseUVs();
            int  countProperties = mesh.CountProperties();

            buffer0.requestProperties(countProperties);
            buffer1.requestProperties(countProperties);
            buffer2.requestProperties(countProperties);

            int   M    = triangleStructure.GetM();
            float step = 1.0f / M;

            CPNSideEdge[] polylines = polygon.sideEdges;
            buffer0.writeWithGuide(polylines[0], M, mesh, evaluator);
            buffer1.writeWithGuide(polylines[1], M, mesh, evaluator);
            buffer2.writeWithGuide(polylines[2], M, mesh, evaluator);

            edgeSurface0.Set(buffer0, buffer2, buffer1);
            edgeSurface1.Set(buffer1, buffer0, buffer2);
            edgeSurface2.Set(buffer2, buffer1, buffer0);

            computeCorners();

            float l1 = ks[0] * ks[1] * ks[0] * ks[1];
            float l2 = ks[1] * ks[2] * ks[1] * ks[2];
            float l3 = ks[2] * ks[0] * ks[2] * ks[0];

            prepareMemory(M, countProperties);

            int position = internalsIndex;

            for (int i = 1; i < M - 1; i++)
            {
                for (int j = 1; j < M - 1 - (i - 1); j++)
                {
                    int k = M - i - j;

                    float U = j * step;
                    float V = i * step;
                    float W = 1 - U - V;

                    float a1 = U * U * W * W * l1 /** buffer0.thickness*/;
                    float a2 = V * V * U * U * l2 /** buffer1.thickness*/;
                    float a3 = W * W * V * V * l3 /** buffer2.thickness*/;

                    //float a1 = W * W;
                    //float a2 = U * U;
                    //float a3 = V * V;

                    if (TriangleInterpolator4.interpolationCorner != 0)
                    {
                        switch (TriangleInterpolator4.interpolationCorner)
                        {
                        case 1: a1 = 1; a2 = 0; a3 = 0; break;

                        case 2: a1 = 0; a2 = 1; a3 = 0; break;

                        case 3: a1 = 0; a2 = 0; a3 = 1; break;
                        }
                    }

                    float rec = 1.0f / (a1 + a2 + a3);
                    a1 *= rec;
                    a2 *= rec;
                    a3 *= rec;


                    Vector3 V1     = edgeSurface0.evalVertex(/*j,*/ i, polylines[0], U / (1 - V));
                    Vector3 V2     = edgeSurface1.evalVertex(/*i,*/ k, polylines[1], V / (1 - W));
                    Vector3 V3     = edgeSurface2.evalVertex(/*k,*/ j, polylines[2], W / (1 - U));
                    Vector3 vertex = V1 * a1 + V2 * a2 + V3 * a3;

                    int memoryIndex = j + i * (M + 1) - (((i) * (i - 1)) >> 1);
                    memory.vertices[memoryIndex] = vertex;

                    if (useUV)
                    {
                        Vector3 V1uv = edgeSurface0.evalUV(/*j,*/ i, polylines[0], U / (1 - V));
                        Vector3 V2uv = edgeSurface1.evalUV(/*i,*/ k, polylines[1], V / (1 - W));
                        Vector3 V3uv = edgeSurface2.evalUV(/*k,*/ j, polylines[2], W / (1 - U));
                        Vector3 uv   = V1uv * a1 + V2uv * a2 + V3uv * a3;
                        //Vector3 vertex = V3;
                        //Vector3 uv = V3uv;

                        memory.uv[memoryIndex] = uv;
                    }

                    for (int pIndex = 0; pIndex < countProperties; pIndex++)
                    {
                        Vector3 V1prop = edgeSurface0.evalProperty(pIndex, i, polylines[0], U / (1 - V));
                        Vector3 V2prop = edgeSurface1.evalProperty(pIndex, k, polylines[1], V / (1 - W));
                        Vector3 V3prop = edgeSurface2.evalProperty(pIndex, j, polylines[2], W / (1 - U));
                        Vector3 prop   = V1prop * a1 + V2prop * a2 + V3prop * a3;
                        mesh.SetProperty3(position, pIndex, prop);
                    }

                    position++;
                }
            }

            position = internalsIndex;

            for (int i = 1; i < M - 1; i++)
            {
                for (int j = 1; j < M - 1 - (i - 1); j++)
                {
                    int rowIndex     = i * (M + 1) - (((i) * (i - 1)) >> 1);
                    int rowIndexPrev = (i - 1) * (M + 1) - (((i - 1) * (i - 2)) >> 1);
                    int rowIndexNext = (i + 1) * (M + 1) - (((i + 1) * (i)) >> 1);

                    int     memoryIndex = j + rowIndex;
                    Vector3 vertex      = memory.vertices[memoryIndex];
                    Vector3 uv          = memory.uv[memoryIndex];

                    Vector3 normal  = Vector3.zero;
                    Vector3 tangent = Vector3.zero;

                    if (useNormals)
                    {
                        //Normal (S is the vertices, the surface)
                        Vector3 dSdu = memory.vertices[memoryIndex + 1] - memory.vertices[memoryIndex - 1];
                        Vector3 dSdv = memory.vertices[rowIndexNext + j] - memory.vertices[rowIndexPrev + j];
                        normal = Vector3.Cross(dSdu, dSdv).normalized;

                        if (useTangents)
                        {
                            //Tangent
                            Vector3 dTxdu = memory.uv[memoryIndex + 1] - memory.uv[memoryIndex - 1];
                            Vector3 dTxdv = memory.uv[rowIndexNext + j] - memory.uv[rowIndexPrev + j];
                            tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);
                        }
                    }

                    mesh.SetPNUV(position, vertex, normal, uv, tangent);

                    position++;
                }
            }

            if (doUpdateStructure)
            {
                triangleStructure.CreateTriangleTessellation(mesh, internalsIndex, facesIndex, polygon);
            }
        }
        public void CreateTriangleTessellation(OutputMesh mesh, int internalsIndex, int facesIndex,
                                               CPNPolygon polygon)
        {
            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
            // internalsIndex:%d facesIndex:%d", internalsIndex, facesIndex);
            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

            CPNSideEdge[] polylines = polygon.sideEdges;
            RetrieveInfos(polygon);

            int trPosition = facesIndex;

            if (M == 1)
            {
                trPosition = mesh.WriteTriangle(trPosition, polylines[0].GetIndex(0), polylines[1].GetIndex(0),
                                                polylines[2].GetIndex(0));
                return;
            }
            else if (M == 2)
            {
                // int[] MS=new int[3];
                MS[0] = polylines[0].GetN();
                MS[1] = polylines[1].GetN();
                MS[2] = polylines[2].GetN();
                for (int i = 0; i < 3; i++)
                {
                    int prev = i == 0 ? 2 : i - 1;
                    if (MS[prev] == 2)
                    {
                        // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                        // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                        // M == 2 i:%d trPosition:%d writing CASE 1",i,trPosition);
                        // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                        trPosition = mesh.WriteTriangle(trPosition,
                                                        polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                        polylines[prev].GetBackIndex(1));
                    }
                    else if (MS[i] == 2)
                    {
                        int other = (i == 2 ? 0 : i + 1);
                        if (MS[other] == 2)
                        {
                            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                            // M == 2 i:%d trPosition:%d writing CASE 2", i,
                            // trPosition);
                            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                            trPosition = mesh.WriteTriangle(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                            polylines[other].GetIndex(1));
                        }
                        else
                        {
                            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                            // M == 2 i:%d trPosition:%d writing CASE 3", i,
                            // trPosition);
                            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                            trPosition = mesh.WriteTriangle(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                            polylines[other].GetIndex(1));
                        }
                    }
                }
                if (MS[0] == 2 && MS[1] == 2 && MS[2] == 2)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // M == 2 writing CASE 4");
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    trPosition = mesh.WriteTriangle(trPosition, polylines[0].GetIndex(1), polylines[1].GetIndex(1),
                                                    polylines[2].GetIndex(1));
                }

                // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                // if(facesIndex+trianglesN!=trPosition)
                // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                // ERROR on trianglesN facesIndex:%d trianglesN:%d trPosition:%d",
                // facesIndex, trianglesN, trPosition);
                // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

                return;
            }

            int innerVerticesPosition = internalsIndex;
            int rowPosition1          = innerVerticesPosition;
            int rowPosition2          = innerVerticesPosition + M - 2;

            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
            // writing Internals innerVerticesPosition:%d rowPosition1:%d
            // rowPosition2:%d", innerVerticesPosition, rowPosition1, rowPosition2);
            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

            for (int i = 0; i < M - 3; i++)
            {
                for (int j_ = 0; j_ < M - 4 - i; j_++)
                {
                    trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j_, rowPosition1 + j_ + 1, rowPosition2 + j_);
                    trPosition = mesh.WriteTriangle(trPosition, rowPosition2 + j_, rowPosition1 + j_ + 1,
                                                    rowPosition2 + j_ + 1);
                }

                int j = M - 4 - i;

                trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j, rowPosition1 + j + 1, rowPosition2 + j);

                rowPosition1 = rowPosition2;
                rowPosition2 = rowPosition2 + (M - 3 - i);
                // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                // writing Internals rowPosition1:%d rowPosition2:%d", rowPosition1,
                // rowPosition2);
                // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            }

            first[0] = innerVerticesPosition;
            first[1] = innerVerticesPosition + M - 3;
            first[2] = innerVerticesPosition + (((M - 1) * (M - 2)) >> 1) - 1;

            move[0] = 1;
            move[1] = M - 2;
            move[2] = -1;

            deltaMove[0] = 0;
            deltaMove[1] = -1;
            deltaMove[2] = -1;

            int count = M - 2;

            // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
            // preparing Sides count:%d first:[%d,%d,%d] move:[%d,%d,%d]
            // deltaMove:[%d,%d,%d]",
            // count, first[0], first[1], first[2], move[0], move[1], move[2],
            // deltaMove[0], deltaMove[1], deltaMove[2]);
            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

            for (int i = 0; i < 3; i++)
            {
                int N = polylines[i].GetN();
                if (N >= 2)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // side Triangle case A trPosition:%d", trPosition);
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    meshIndicesArray.Setup(first[i], move[i], deltaMove[i], count, mesh,
                                           TriangleMeshStructure.DEFAULT_VERTICES_LAYER);

                    NetPolylineInternalIndicesArray npi = new NetPolylineInternalIndicesArray(polylines[i], mesh);
                    trPosition = MeshStructures.CreateSideTriangles(mesh, meshIndicesArray, npi, trPosition);
                }
                else if (N == 1)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // side Triangle case B trPosition:%d (Begin)", trPosition);
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    meshIndicesArray.Setup(first[i], move[i], deltaMove[i], count, mesh, DEFAULT_VERTICES_LAYER);

                    NetPolylineIndicesArray npi = new NetPolylineIndicesArray(polylines[i], mesh);
                    trPosition = MeshStructures.CreateSideTriangles(mesh, meshIndicesArray, npi, trPosition);

                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // side Triangle case B trPosition:%d (End)", trPosition);
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                }

                int prev  = i == 0 ? 2 : i - 1;
                int prevN = polylines[prev].GetN();
                if (N > 1 && prevN > 1)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // writing corner Index as Quad a:%d b:%d c:%d d:%d",
                    // polylines[i].getIndex(1),first[i],
                    // polylines[prev].getBackIndex(1), polylines[i].getIndex(0));
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

                    if (prevN + N < 1.5f * M)
                    {
                        trPosition = mesh.WriteQuad(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                    first[i], polylines[prev].GetBackIndex(1));
                    }
                    else
                    {
                        trPosition = mesh.WriteQuad(trPosition, polylines[i].GetIndex(1), first[i],
                                                    polylines[prev].GetBackIndex(1), polylines[i].GetIndex(0));
                    }
                }
                else if (polylines[i].GetN() > 1)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // writing corner Index as Triangle a:%d b:%d c:%d ",
                    // polylines[i].getIndex(0), polylines[i].getIndex(1),
                    // first[i]);
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

                    trPosition = mesh.WriteTriangle(trPosition, polylines[i].GetIndex(0), polylines[i].GetIndex(1),
                                                    first[i]);
                }
                else if (polylines[prev].GetN() > 1)
                {
                    // #ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
                    // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
                    // writing corner Index as Triangle a:%d b:%d c:%d ",
                    // polylines[i].getIndex(0),
                    // first[i],polylines[i].getBackIndex(1));
                    // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR

                    trPosition = mesh.WriteTriangle(trPosition, polylines[i].GetIndex(0), first[i],
                                                    polylines[prev].GetBackIndex(1));
                }
            }

            // #
            // ifdef SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
            // if(facesIndex+trianglesN!=trPosition)
            //
            // printf("\nSFCPNTrianglesMeshStructure.createTriangleTessellation
            // ERROR on trianglesN facesIndex:%d trianglesN:%d trPosition:%d",
            // facesIndex, trianglesN, trPosition);
            // #endif //SF_RAW_DEBUG_TRIANGLE_TESSELLATOR
        }
Beispiel #12
0
        public void UdpdateContent(OutputMesh mesh, CPNPolygon polygon, int internalsIndex,
                                   int facesIndex, bool doUpdateStructure = true)
        {
            quadStructure.RetrieveInfos(polygon);

            int   MV    = quadStructure.GetMV();
            int   MH    = quadStructure.GetMH();
            float stepV = 1.0f / MV;
            float stepH = 1.0f / MH;

            CPNSideEdge[] polylines = polygon.sideEdges;
            buffer0.writeWithGuide(polylines[0], MH, mesh, evaluator);
            buffer1.writeWithGuide(polylines[1], MV, mesh, evaluator);
            buffer2.writeWithGuide(polylines[2], MH, mesh, evaluator);
            buffer3.writeWithGuide(polylines[3], MV, mesh, evaluator);

            edgeSurface0.Set(buffer0, buffer3, buffer1);
            edgeSurface1.Set(buffer1, buffer0, buffer2);
            edgeSurface2.Set(buffer2, buffer1, buffer3);
            edgeSurface3.Set(buffer3, buffer2, buffer0);

            computeCorners();

            float l1 = ks[0] * ks[1] * ks[0] * ks[1];
            float l2 = ks[1] * ks[2] * ks[1] * ks[2];
            float l3 = ks[2] * ks[3] * ks[2] * ks[3];
            float l4 = ks[3] * ks[0] * ks[3] * ks[0];

            prepareMemory(MH, MV);

            for (int i = 1; i < MV; i++)
            {
                for (int j = 1; j < MH; j++)
                {
                    float U = (j) * stepH;
                    float V = (i) * stepV;

                    Vector3 V1 = edgeSurface0.evalVertex(j, i);
                    Vector3 V2 = edgeSurface1.evalVertex(i, MH - j);
                    Vector3 V3 = edgeSurface2.evalVertex(MH - j, MV - i);
                    Vector3 V4 = edgeSurface3.evalVertex(MV - i, j);

                    Vector3 V1uv = edgeSurface0.evalUV(j, i);
                    Vector3 V2uv = edgeSurface1.evalUV(i, MH - j);
                    Vector3 V3uv = edgeSurface2.evalUV(MH - j, MV - i);
                    Vector3 V4uv = edgeSurface3.evalUV(MV - i, j);

                    float UM = 1 - U;
                    float VM = 1 - V;

                    float a1 = U * U * VM * VM * UM * UM * l1 /** buffer0.thickness*/;
                    float a2 = VM * VM * U * U * V * V * l2 /** buffer1.thickness*/;
                    float a3 = UM * UM * V * V * U * U * l3 /** buffer2.thickness*/;
                    float a4 = V * V * UM * UM * VM * VM * l4 /** buffer3.thickness*/;

#if DEBUG
                    if (TriangleInterpolator4.interpolationCorner != 0)
                    {
                        switch (TriangleInterpolator4.interpolationCorner)
                        {
                        case 1: a1 = 1; a2 = 0; a3 = 0; a4 = 0; break;

                        case 2: a1 = 0; a2 = 1; a3 = 0; a4 = 0; break;

                        case 3: a1 = 0; a2 = 0; a3 = 1; a4 = 0; break;

                        case 4: a1 = 0; a2 = 0; a3 = 0; a4 = 1; break;
                        }
                    }
#endif

                    float rec = 1.0f / (a1 + a2 + a3 + a4);
                    a1 *= rec;
                    a2 *= rec;
                    a3 *= rec;
                    a4 *= rec;

                    Vector3 vertex = a1 * V1 + a2 * V2 + a3 * V3 + a4 * V4;
                    //Vector3 vertex = V3;
                    Vector3 uv = a1 * V1uv + a2 * V2uv + a3 * V3uv + a4 * V4uv;
                    //Vector3 uv = V3uv;

                    int memoryIndex = j + i * (MH + 1);
                    memory.vertices[memoryIndex] = vertex;
                    memory.uv[memoryIndex]       = uv;
                }
            }

            int index = internalsIndex;
            for (int i = 1; i < MV; i++)
            {
                for (int j = 1; j < MH; j++)
                {
                    int rowIndex     = i * (MH + 1);
                    int rowIndexPrev = (i - 1) * (MH + 1);
                    int rowIndexNext = (i + 1) * (MH + 1);

                    int     memoryIndex = j + rowIndex;
                    Vector3 vertex      = memory.vertices[memoryIndex];
                    Vector3 uv          = memory.uv[memoryIndex];

                    //Normal (S is the vertices, the surface)
                    Vector3 dSdu = memory.vertices[memoryIndex + 1] - memory.vertices[memoryIndex - 1];
                    Vector3 dSdv = memory.vertices[rowIndexNext + j] - memory.vertices[rowIndexPrev + j];
                    dSdu = dSdu.normalized;
                    dSdv = dSdv.normalized;
                    Vector3 normal = Vector3.Cross(dSdu, dSdv).normalized;

                    //Debug.Log("dSdu: (" + dSdu.x + "," + dSdu.y + "," + dSdu.z + ") dSdv:"
                    //    + dSdv.x + "," + dSdv.y + "," + dSdv.z + ") Vector3.Cross(dSdu, dSdv).magnitude:" + Vector3.Cross(dSdu, dSdv).magnitude);
                    //Debug.Log("Normal (" + normal.x + "," + normal.y + "," + normal.z + ")");

                    //Tangent
                    Vector3 dTxdu   = memory.uv[memoryIndex + 1] - memory.uv[memoryIndex - 1];
                    Vector3 dTxdv   = memory.uv[rowIndexNext + j] - memory.uv[rowIndexPrev + j];
                    Vector3 tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);

                    mesh.SetPNUV(index, vertex, normal, uv, tangent);

                    index++;
                }
            }

            if (doUpdateStructure)
            {
                quadStructure.CreateQuadTessellation(mesh, internalsIndex, facesIndex, polygon);
            }
        }
        public void UdpdateContent(OutputMesh mesh, CPNPolygon buildingPolygonData, int internalsIndex,
                                   int facesIndex, bool doUpdateStructure = true)
        {
            RetrieveInfos(buildingPolygonData);

            this.step = 1.0f / M;

            totalInterpolationStep = M / relativeTriangleFactorX;
            interpolationSteps     = (int)(totalInterpolationStep);
            if (interpolationSteps * relativeTriangleFactorX < M)
            {
                interpolationSteps++;
            }

            Vector3 vertex = Vector3.zero;
            Vector3 uv     = Vector3.zero;

            int centerPiecePosition = 0;

            int verticesLayer = 0;// mesh.FindLayer(BufferType.VERTICES);

            //int normalsLayer = mesh.FindLayer(BufferType.NORMALS);
            //cornerSurfacesSet.SetNormalsLayer(normalsLayer);

            CPNSideEdge[] polylines = buildingPolygonData.sideEdges;

            for (int i = 0; i < sides; i++)
            {
                buffers[i].writeWithGuide(polylines[i], interpolationSteps, step * relativeTriangleFactorX, mesh, evaluator);
                backBuffers[i].writeWithGuideBack(polylines[i], interpolationSteps, step * relativeTriangleFactorX, mesh, evaluator);
            }

            prepareMemory(M, polylines, mesh);

            //int position = internalsIndex;

            int triangleSize = ((M)*(M + 1)) >> 1;

            for (int corner = 0; corner < sides; corner++)
            {
                int next = corner == sides - 1 ? 0 : corner + 1;

                float p1x = cos_[corner];
                float p2x = cos_[next];
                float p1y = sin_[corner];
                float p2y = sin_[next];

                int relativeMemoryIndex = triangleSize * corner + M;

                for (int i = 1; i <= M - 1; i++)
                {
                    for (int j = 0; j <= M - 1 - i; j++)
                    {
                        float innerU = step * j;
                        float innerV = step * i;
                        float innerW = 1 - innerU - innerV;

                        float innerX_ = innerW * p1x + innerU * p2x;
                        float innerY_ = innerW * p1y + innerU * p2y;

                        vertex = EvalVertex(mesh, buildingPolygonData, innerX_, innerY_, out uv);

                        memory.vertices[relativeMemoryIndex] = vertex;
                        memory.uv[relativeMemoryIndex]       = uv;
                        relativeMemoryIndex++;
                        //position++;
                    }
                }
            }

            vertex = EvalVertex(mesh, buildingPolygonData, 0, 0, out uv);
            //mesh.SetValue(0, position, vertex);
            memory.vertices[triangleSize * sides] = vertex;
            memory.uv[triangleSize * sides]       = uv;
            //position++;



            //Phase 2 Normals and Tangents Evaluation

            int position = internalsIndex;

            for (int corner = 0; corner < sides; corner++)
            {
                int prev = corner == 0 ? sides - 1 : corner - 1;
                int next = corner == sides - 1 ? 0 : corner + 1;
                int relativeMemoryIndex          = triangleSize * corner;
                int nextPatchRelativeMemoryIndex = triangleSize * next;
                int prevPatchRelativeMemoryIndex = triangleSize * prev;
                slicePosition[corner] = position;
                for (int i = 1; i <= M - 1; i++)
                {
                    for (int j = 0; j <= M - 1 - i; j++)
                    {
                        int rowIndex     = relativeMemoryIndex + M * i - (((i) * (i - 1)) >> 1);
                        int prevRowIndex = relativeMemoryIndex + M * (i - 1) - (((i - 1) * (i - 2)) >> 1);
                        int nextRowIndex = relativeMemoryIndex + M * (i + 1) - (((i + 1) * (i)) >> 1);

                        int index = rowIndex + j;
                        vertex = memory.vertices[index];
                        uv     = memory.uv[index];

                        int duIndexA = 0, duIndexB = 0, dvIndexA = 0, dvIndexB = 0;
                        if (j > 0 && j < M - 1 - i)
                        {
                            duIndexA = prevRowIndex + j;
                            duIndexB = nextRowIndex + j;
                            dvIndexA = nextRowIndex + j - 1;
                            dvIndexB = prevRowIndex + j + 1;
                        }
                        else if (i < M - 1)
                        {
                            if (j == M - 1 - i)
                            {
                                int nextPatchnextRowIndex = nextPatchRelativeMemoryIndex + M * (i + 1) - (((i + 1) * (i)) >> 1);

                                duIndexA = prevRowIndex + j;
                                duIndexB = nextPatchnextRowIndex;
                                dvIndexA = nextRowIndex + j - 1;
                                dvIndexB = prevRowIndex + j + 1;
                            }
                            else if (j == 0)
                            {
                                int prevPatchprevRowIndex = prevPatchRelativeMemoryIndex + M * (i - 1) - (((i - 1) * (i - 2)) >> 1);

                                duIndexA = prevRowIndex + j;
                                duIndexB = nextRowIndex + j;
                                dvIndexA = prevPatchprevRowIndex + M - i;
                                dvIndexB = prevRowIndex + j + 1;
                            }
                        }
                        else
                        {
                            int prevPatchprevRowIndex = prevPatchRelativeMemoryIndex + M * (i - 1) - (((i - 1) * (i - 2)) >> 1);

                            duIndexA = prevRowIndex + j;
                            duIndexB = triangleSize * sides;
                            dvIndexA = prevPatchprevRowIndex + M - i;
                            dvIndexB = prevRowIndex + j + 1;
                        }


                        Vector3 dSdu   = memory.vertices[duIndexB] - memory.vertices[duIndexA];
                        Vector3 dSdv   = memory.vertices[dvIndexB] - memory.vertices[dvIndexA];
                        Vector3 normal = Vector3.Cross(dSdu, dSdv).normalized;

                        //Tangent
                        Vector3 dTxdu   = memory.uv[duIndexB] - memory.uv[duIndexA];
                        Vector3 dTxdv   = memory.uv[dvIndexB] - memory.uv[dvIndexA];
                        Vector3 tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);

                        mesh.SetPNUV(position, vertex, normal, uv, tangent);

                        //relativeMemoryIndex++;
                        position++;
                    }
                }
            }

            {
                int duIndexA = 2 * triangleSize - 1;
                int duIndexB = 4 * triangleSize - 1;
                int dvIndexA = triangleSize - 1;
                int dvIndexB = 3 * triangleSize - 1;
                vertex = memory.vertices[triangleSize * sides];
                uv     = memory.uv[triangleSize * sides];

                Vector3 dSdu   = memory.vertices[duIndexB] - memory.vertices[duIndexA];
                Vector3 dSdv   = memory.vertices[dvIndexB] - memory.vertices[dvIndexA];
                Vector3 normal = Vector3.Cross(dSdu, dSdv).normalized;

                //Tangent
                Vector3 dTxdu   = memory.uv[duIndexB] - memory.uv[duIndexA];
                Vector3 dTxdv   = memory.uv[dvIndexB] - memory.uv[dvIndexA];
                Vector3 tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);
                mesh.SetPNUV(position, vertex, normal, uv, tangent);
            }

            centerPiecePosition = position;
            position++;



            int trPosition = facesIndex;

            for (int corner = 0; corner < sides; corner++)
            {
                int next = corner == sides - 1 ? 0 : corner + 1;

                if (M > 1)
                {
                    int rowPosition1     = slicePosition[corner];
                    int rowPosition2     = slicePosition[corner] + M - 1;
                    int rowPosition1Next = slicePosition[next];
                    int rowPosition2Next = slicePosition[next] + M - 1;
                    for (int i = 0; i < M - 2; i++)
                    {
                        for (int j_ = 0; j_ < M - 3 - i; j_++)
                        {
                            trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j_, rowPosition2 + j_, rowPosition1 + j_ + 1);
                            trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j_ + 1, rowPosition2 + j_, rowPosition2 + j_ + 1);
                        }
                        int j = M - 3 - i;
                        trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j,
                                                        rowPosition2 + j, rowPosition1 + j + 1);

                        trPosition = mesh.WriteTriangle(trPosition, rowPosition2 + j,
                                                        rowPosition2Next, rowPosition1 + j + 1);

                        trPosition = mesh.WriteTriangle(trPosition, rowPosition1 + j + 1,
                                                        rowPosition2Next, rowPosition1Next);

                        rowPosition1     = rowPosition2;
                        rowPosition2     = rowPosition2 + M - 2 - i;
                        rowPosition1Next = rowPosition2Next;
                        rowPosition2Next = rowPosition2Next + M - 2 - i;
                    }
                    trPosition = mesh.WriteTriangle(trPosition, rowPosition1, centerPiecePosition, rowPosition1Next);

                    meshIndicesArray.Setup(slicePosition[corner], 1, M, slicePosition[next], mesh, verticesLayer);

                    int polylineIndex = sides - 1 - corner;

                    NetPolylineIndicesArray npi = new NetPolylineIndicesArray(polylines[polylineIndex], mesh, true);
                    trPosition = MeshStructures.CreateSideTriangles(mesh, npi, meshIndicesArray,
                                                                    trPosition);
                }
                else

                {
                    trPosition = mesh.WriteTriangle(trPosition, polylines[corner].GetIndex(0), centerPiecePosition, polylines[corner].GetBackIndex(0));
                }
            }
        }
Beispiel #14
0
        public void UdpdateContent(OutputMesh mesh, CPNPolygon polygon, int internalsIndex,
                                   int facesIndex, bool doUpdateStructure = true)
        {
            quadStructure.RetrieveInfos(polygon);

            bool useUV           = mesh.DoUseUVs();
            bool useNormals      = mesh.DoNormals();
            bool useTangents     = mesh.DoUseUVs();
            int  countProperties = mesh.CountProperties();

            buffer0.requestProperties(countProperties);
            buffer1.requestProperties(countProperties);
            buffer2.requestProperties(countProperties);
            buffer3.requestProperties(countProperties);

            int   MV    = quadStructure.GetMV();
            int   MH    = quadStructure.GetMH();
            float stepV = 1.0f / MV;
            float stepH = 1.0f / MH;

            CPNSideEdge[] polylines = polygon.sideEdges;
            buffer0.writeWithGuide(polylines[0], MH, mesh, evaluator);
            buffer1.writeWithGuide(polylines[1], MV, mesh, evaluator);
            buffer2.writeWithGuide(polylines[2], MH, mesh, evaluator);
            buffer3.writeWithGuide(polylines[3], MV, mesh, evaluator);

            edgeSurface0.Set(buffer0, buffer3, buffer1);
            edgeSurface1.Set(buffer1, buffer0, buffer2);
            edgeSurface2.Set(buffer2, buffer1, buffer3);
            edgeSurface3.Set(buffer3, buffer2, buffer0);

            //float l1 = ks[0] * ks[1] * ks[0] * ks[1];
            //float l2 = ks[1] * ks[2] * ks[1] * ks[2];
            //float l3 = ks[2] * ks[3] * ks[2] * ks[3];
            //float l4 = ks[3] * ks[0] * ks[3] * ks[0];
            float l1 = GetBufferLength(buffer0);
            float l2 = GetBufferLength(buffer1);
            float l3 = GetBufferLength(buffer2);
            float l4 = GetBufferLength(buffer3);

            prepareMemory(MH, MV);

            int index = internalsIndex;

            for (int i = 1; i < MV; i++)
            {
                for (int j = 1; j < MH; j++)
                {
                    float U = (j) * stepH;
                    float V = (i) * stepV;

                    float UM = 1 - U;
                    float VM = 1 - V;

                    float a1 = U * U * VM * VM * UM * UM * l1 /** buffer0.thickness*/;
                    float a2 = VM * VM * U * U * V * V * l2 /** buffer1.thickness*/;
                    float a3 = UM * UM * V * V * U * U * l3 /** buffer2.thickness*/;
                    float a4 = V * V * UM * UM * VM * VM * l4 /** buffer3.thickness*/;

#if DEBUG
                    if (TriangleInterpolator4.interpolationCorner != 0)
                    {
                        switch (TriangleInterpolator4.interpolationCorner)
                        {
                        case 1: a1 = 1; a2 = 0; a3 = 0; a4 = 0; break;

                        case 2: a1 = 0; a2 = 1; a3 = 0; a4 = 0; break;

                        case 3: a1 = 0; a2 = 0; a3 = 1; a4 = 0; break;

                        case 4: a1 = 0; a2 = 0; a3 = 0; a4 = 1; break;
                        }
                    }
#endif

                    float rec = 1.0f / (a1 + a2 + a3 + a4);
                    a1 *= rec;
                    a2 *= rec;
                    a3 *= rec;
                    a4 *= rec;

                    Vector3 V1          = edgeSurface0.evalVertex(j, i);
                    Vector3 V2          = edgeSurface1.evalVertex(i, MH - j);
                    Vector3 V3          = edgeSurface2.evalVertex(MH - j, MV - i);
                    Vector3 V4          = edgeSurface3.evalVertex(MV - i, j);
                    Vector3 vertex      = a1 * V1 + a2 * V2 + a3 * V3 + a4 * V4;
                    int     memoryIndex = j + i * (MH + 1);
                    memory.vertices[memoryIndex] = vertex;

                    if (useUV)
                    {
                        Vector3 V1uv = edgeSurface0.evalUV(j, i);
                        Vector3 V2uv = edgeSurface1.evalUV(i, MH - j);
                        Vector3 V3uv = edgeSurface2.evalUV(MH - j, MV - i);
                        Vector3 V4uv = edgeSurface3.evalUV(MV - i, j);
                        //Vector3 vertex = V3;
                        Vector3 uv = a1 * V1uv + a2 * V2uv + a3 * V3uv + a4 * V4uv;
                        //Vector3 uv = V3uv;
                        memory.uv[memoryIndex] = uv;
                    }

                    for (int k = 0; k < countProperties; k++)
                    {
                        Vector3 V1propK = edgeSurface0.evalProperty(k, j, i);
                        Vector3 V2propK = edgeSurface1.evalProperty(k, i, MH - j);
                        Vector3 V3propK = edgeSurface2.evalProperty(k, MH - j, MV - i);
                        Vector3 V4propK = edgeSurface3.evalProperty(k, MV - i, j);
                        Vector3 propK   = a1 * V1propK + a2 * V2propK + a3 * V3propK + a4 * V4propK;
                        mesh.SetProperty3(index, k, propK);
                    }

                    index++;
                }
            }

            index = internalsIndex;
            for (int i = 1; i < MV; i++)
            {
                for (int j = 1; j < MH; j++)
                {
                    int rowIndex     = i * (MH + 1);
                    int rowIndexPrev = (i - 1) * (MH + 1);
                    int rowIndexNext = (i + 1) * (MH + 1);

                    int     memoryIndex = j + rowIndex;
                    Vector3 vertex      = memory.vertices[memoryIndex];
                    Vector3 uv          = memory.uv[memoryIndex];

                    Vector3 normal  = Vector3.zero;
                    Vector3 tangent = Vector3.zero;

                    if (useNormals)
                    {
                        Vector3 dSdu = memory.vertices[memoryIndex + 1] - memory.vertices[memoryIndex - 1];
                        Vector3 dSdv = memory.vertices[rowIndexNext + j] - memory.vertices[rowIndexPrev + j];
                        dSdu   = dSdu.normalized;
                        dSdv   = dSdv.normalized;
                        normal = Vector3.Cross(dSdu, dSdv).normalized;

                        if (useTangents)
                        {
                            //Tangent
                            Vector3 dTxdu = memory.uv[memoryIndex + 1] - memory.uv[memoryIndex - 1];
                            Vector3 dTxdv = memory.uv[rowIndexNext + j] - memory.uv[rowIndexPrev + j];
                            tangent = getTangent(dSdu, dSdv, dTxdu, dTxdv);
                        }
                    }

                    mesh.SetPNUV(index, vertex, normal, uv, tangent);

                    index++;
                }
            }

            if (doUpdateStructure)
            {
                quadStructure.CreateQuadTessellation(mesh, internalsIndex, facesIndex, polygon);
            }
        }