コード例 #1
0
    // Creating a dictionary mapping from new points to their corresponding edge midpoints
    private static Dictionary <int, List <Vector3> > CreatePointsToEdgeMidpointsMap(CCMeshData mesh)
    {
        Dictionary <int, List <Vector3> > pointsToAvgEdgesMap = new Dictionary <int, List <Vector3> >();

        foreach (var edge in mesh.edges)
        {
            var p1  = (int)edge[0];
            var p2  = (int)edge[1];
            var avg = (mesh.points[p1] + mesh.points[p2]) / 2;
            if (!pointsToAvgEdgesMap.ContainsKey(p1))
            {
                pointsToAvgEdgesMap[p1] = new List <Vector3>();
            }

            if (!pointsToAvgEdgesMap.ContainsKey(p2))
            {
                pointsToAvgEdgesMap[p2] = new List <Vector3>();
            }

            pointsToAvgEdgesMap[p1].Add(avg);
            pointsToAvgEdgesMap[p2].Add(avg);
        }

        return(pointsToAvgEdgesMap);
    }
コード例 #2
0
ファイル: CatmullClark.cs プロジェクト: damebrown/CG_ex3
    // Returns a list of new locations of the original points for the given CCMeshData, as described in the CC algorithm
    public static List <Vector3> GetNewPoints(CCMeshData mesh)
    {
        List <Vector3> new_points = new List <Vector3>(mesh.points);

        Vector3[] edges_avg     = new Vector3[mesh.points.Count];
        int[]     edges_counter = new int[mesh.points.Count];
        Vector3[] faces_avg     = new Vector3[mesh.points.Count];
        int[]     faces_counter = new int[mesh.points.Count];
        foreach (Vector4 edge in mesh.edges)
        {
            Vector3 avg = (mesh.points[(int)edge[0]] + mesh.points[(int)edge[1]]) / 2;
            edges_avg[(int)edge[0]] += avg;
            edges_counter[(int)edge[0]]++;
            edges_avg[(int)edge[1]] += avg;
            edges_counter[(int)edge[1]]++;
        }
        for (int i = 0; i < mesh.faces.Count; ++i)
        {
            for (int j = 0; j < 4; ++j)
            {
                faces_avg[(int)mesh.faces[i][j]] += mesh.facePoints[i];
                faces_counter[(int)mesh.faces[i][j]]++;
            }
        }
        for (int i = 0; i < new_points.Count; ++i)
        {
            edges_avg[i] /= edges_counter[i];
            faces_avg[i] /= faces_counter[i];
            new_points[i] = (faces_avg[i] + 2 * (edges_avg[i]) + ((faces_counter[i] - 3) * mesh.points[i])) / faces_counter[i];
        }
        return(new_points);
    }
コード例 #3
0
    //return the edges that touches a original point at specific face key = (face, point), value = list of edges (2)
    public static Dictionary <Vector2, List <int> > edges_dict(CCMeshData meshData)
    {
        var result = new Dictionary <Vector2, List <int> >();

        for (int i = 0; i < meshData.edges.Count; i++)
        {
            for (int f_idx = 2; f_idx < 4; f_idx++)
            {
                var f = meshData.edges[i][f_idx];
                if (f == -1)
                {
                    continue;
                }
                for (int p_idx = 0; p_idx < 2; p_idx++)
                {
                    var p   = meshData.edges[i][p_idx];
                    var key = new Vector2(f, p);
                    if (!result.ContainsKey(key))
                    {
                        result[key] = new List <int>();
                    }
                    result[key].Add(i);
                }
            }
        }
        return(result);
    }
コード例 #4
0
    // Returns a list of all edges in the mesh defined by given points and faces.
    // Each edge is represented by Vector4(p1, p2, f1, f2)
    // p1, p2 are the edge vertices
    // f1, f2 are faces incident to the edge. If the edge belongs to one face only, f2 is -1
    public static List <Vector4> GetEdges(CCMeshData mesh)
    {
        var edgeDict = new Dictionary <int[], Vector4>(new EdgeComparer());

        // Iterate over faces, add as values to dictionary[current edge]
        for (var faceIdx = 0; faceIdx < mesh.faces.Count; ++faceIdx)
        {
            for (var idx = 0; idx < 4; ++idx)
            {
                var currentKey = new int[2]
                {
                    (int)mesh.faces[faceIdx][idx % 4], (int)mesh.faces[faceIdx][(idx + 1) % 4]
                };
                if (edgeDict.ContainsKey(currentKey))
                {
                    edgeDict[currentKey] = new Vector4(edgeDict[currentKey].x, edgeDict[currentKey].y,
                                                       edgeDict[currentKey].z, faceIdx);
                }
                else
                {
                    edgeDict[currentKey] = new Vector4(currentKey[0], currentKey[1], faceIdx, -1);
                }
            }
        }

        return(edgeDict.Values.ToList());
    }
コード例 #5
0
    //return dictionary of the index for the new points
    public static Dictionary <Vector3, int> getPointDict(CCMeshData meshData, List <Vector3> vertices)
    {
        var dict    = new Dictionary <Vector3, int>();
        var cur_idx = 0;

        for (int i = 0; i < meshData.facePoints.Count; i++)
        {
            vertices.Add(meshData.facePoints[i]);
            dict[meshData.facePoints[i]] = cur_idx;
            cur_idx++;
        }
        for (int i = 0; i < meshData.edgePoints.Count; i++)
        {
            vertices.Add(meshData.edgePoints[i]);
            dict[meshData.edgePoints[i]] = cur_idx;
            cur_idx++;
        }
        for (int i = 0; i < meshData.newPoints.Count; i++)
        {
            vertices.Add(meshData.newPoints[i]);
            dict[meshData.newPoints[i]] = cur_idx;
            cur_idx++;
        }

        return(dict);
    }
コード例 #6
0
    //Creating the new mesh after the subdivision
    private static QuadMeshData CreateNewQuadMeshData(CCMeshData mesh)
    {
        var vertices = mesh.newPoints.Concat(mesh.edgePoints.Concat(mesh.facePoints)).ToList();
        var quads    = QuadsFromDict(mesh.pairToEdgeMapping);

        return(new QuadMeshData(vertices, quads));
    }
コード例 #7
0
    // Returns a list of "edge points" for the given CCMeshData, as described in the Catmull-Clark algorithm
    public static List <Vector3> GetEdgePoints(CCMeshData mesh)
    {
        mesh.pairToEdgeMapping = new Dictionary <int[], int[]>(new EdgeComparer());

        return(mesh.edges.Select((edge, idx) =>
        {
            var edgesOffset = mesh.points.Count;              // offset of edge points in final QuadMeshData vertices
            var facesOffset = edgesOffset + mesh.edges.Count; // offset of face points in final QuadMeshData vertices
            var p1 = (int)edge[0];
            var p2 = (int)edge[1];
            var f1 = (int)edge[2];
            var f2 = (int)edge[3];

            // Add pairs (f1, p1), (p2, f1) (and if f2 exists (p1, f2), (f2, p2)) and their connecting edge points
            // (f1, p1) and (f2, p2) added in reverse order from (p2, f1) and (p1, f2) to get a clockwise sequence
            var pair1 = new int[2] {
                f1 + facesOffset, p1
            };
            var pair2 = new int[2] {
                p2, f1 + facesOffset
            };
            var pairs = new List <int[]>()
            {
                pair1, pair2
            };
            if (f2 != -1)
            {
                var pair3 = new int[2] {
                    p1, f2 + facesOffset
                };
                var pair4 = new int[2] {
                    f2 + facesOffset, p2
                };
                pairs.AddRange(new[] { pair3, pair4 });
            }

            // Map to index of edge point being calculated
            foreach (var pair in pairs)
            {
                mesh.pairToEdgeMapping[pair] = mesh.pairToEdgeMapping.ContainsKey(pair)
                    ? new int[2] {
                    mesh.pairToEdgeMapping[pair][0], idx + edgesOffset
                }
                    : new int[] { idx + edgesOffset };
            }

            // Calculate edge point
            var numToDivide = 3;
            var lastFacePoint = Vector3.zero;
            if (f2 != -1)
            {
                numToDivide = 4;
                lastFacePoint = mesh.facePoints[f2];
            }

            return (mesh.points[p1] + mesh.points[p2] + mesh.facePoints[f1] + lastFacePoint) / numToDivide;
        }).ToList());
    }
コード例 #8
0
ファイル: CatmullClark.cs プロジェクト: damebrown/CG_ex3
    // Returns a list of "edge points" for the given CCMeshData, as described in the Catmull-Clark algorithm
    public static List <Vector3> GetEdgePoints(CCMeshData mesh)
    {
        List <Vector3> edge_points = new List <Vector3>();

        foreach (Vector4 edge in mesh.edges)
        {
            Vector3 new_point = (mesh.points[(int)edge[0]] + mesh.points[(int)edge[1]] + mesh.facePoints[(int)edge[2]] + mesh.facePoints[(int)edge[3]]) / 4;
            edge_points.Add(new_point);
        }
        return(edge_points);
    }
コード例 #9
0
ファイル: CatmullClark.cs プロジェクト: damebrown/CG_ex3
    // Returns a list of "face points" for the given CCMeshData, as described in the Catmull-Clark algorithm
    public static List <Vector3> GetFacePoints(CCMeshData mesh)
    {
        List <Vector3> face_points = new List <Vector3>();

        foreach (Vector4 face in mesh.faces)
        {
            Vector3 new_point = (mesh.points[(int)face[0]] + mesh.points[(int)face[1]] + mesh.points[(int)face[2]] + mesh.points[(int)face[3]]) / 4;
            face_points.Add(new_point);
        }
        return(face_points);
    }
コード例 #10
0
    // Returns a QuadMeshData representing the input mesh after one iteration of Catmull-Clark subdivision.
    public static QuadMeshData Subdivide(QuadMeshData quadMeshData)
    {
        // Create and initialize a CCMeshData corresponding to the given QuadMeshData
        CCMeshData meshData = new CCMeshData();

        meshData.points     = quadMeshData.vertices;
        meshData.faces      = quadMeshData.quads;
        meshData.edges      = GetEdges(meshData);
        meshData.facePoints = GetFacePoints(meshData);
        meshData.edgePoints = GetEdgePoints(meshData);
        meshData.newPoints  = GetNewPoints(meshData);

        // Combine facePoints, edgePoints and newPoints into a subdivided QuadMeshData
        return(CreateNewQuadMeshData(meshData));
    }
コード例 #11
0
    // Returns a list of "face points" for the given CCMeshData, as described in the Catmull-Clark algorithm
    public static List <Vector3> GetFacePoints(CCMeshData mesh)
    {
        List <Vector3> facePoints = new List <Vector3>();

        for (int i = 0; i < mesh.faces.Count; i++)
        {
            Vector3 facePoint = Vector3.zero;
            for (int j = 0; j < 4; j++)
            {
                facePoint += mesh.points[(int)mesh.faces[i][j]];
            }
            facePoint /= 4;
            facePoints.Add(facePoint);
        }
        return(facePoints);
    }
コード例 #12
0
    // Returns a list of all edges in the mesh defined by given points and faces.
    // Each edge is represented by Vector4(p1, p2, f1, f2)
    // p1, p2 are the edge vertices
    // f1, f2 are faces incident to the edge. If the edge belongs to one face only, f2 is -1
    public static List <Vector4> GetEdges(CCMeshData mesh)
    {
        Vec2Comparer c = new Vec2Comparer();
        Dictionary <Vector2, Vector4> edges = new Dictionary <Vector2, Vector4>(c);

        for (int i = 0; i < mesh.faces.Count; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                Vector2 edgeVertices = new Vector2(mesh.faces[i][j], mesh.faces[i][j + 1]);
                addEdge(edgeVertices, edges, i);
            }
            //adding the last edge
            Vector2 edgeVertices1 = new Vector2(mesh.faces[i][3], mesh.faces[i][0]);
            addEdge(edgeVertices1, edges, i);
        }
        return(edges.Values.ToList());
    }
コード例 #13
0
    // Returns a list of new locations of the original points for the given CCMeshData, as described in the CC algorithm
    public static List <Vector3> GetNewPoints(CCMeshData mesh)
    {
        var dataPoints = createList(mesh.points.Count);

        // foreach(var edge in mesh.edges)
        for (int j = 0; j < mesh.edges.Count; j++)
        {
            int p1      = (int)mesh.edges[j][0];
            int p2      = (int)mesh.edges[j][1];
            var midEdge = (mesh.points[p1] + mesh.points[p2]) / 2;
            dataPoints[p1].r += midEdge;
            dataPoints[p2].r += midEdge;
            for (int i = 2; i < 4; i++)
            {
                int face = (int)mesh.edges[j][i];

                if (!dataPoints[p1].visited.Contains(face))
                {
                    dataPoints[p1].visited.Add(face);
                    dataPoints[p1].f += mesh.facePoints[face];
                    dataPoints[p1].n++;
                }
                if (!dataPoints[p2].visited.Contains(face))
                {
                    dataPoints[p2].visited.Add(face);
                    dataPoints[p2].f += mesh.facePoints[face];
                    dataPoints[p2].n++;
                }
            }
        }

        var newPoints = new List <Vector3>();

        for (int i = 0; i < mesh.points.Count; i++)
        {
            var p        = dataPoints[i];
            var position = (p.f) / p.n + 2 * p.r / p.n + (p.n - 3) * mesh.points[i];
            position /= p.n;
            newPoints.Add(position);
        }

        return(newPoints);
    }
コード例 #14
0
    // Returns a list of new locations of the original points for the given CCMeshData, as described in the CC algorithm
    public static List <Vector3> GetNewPoints(CCMeshData mesh)
    {
        var pointsToEdgePointsMap = CreatePointsToEdgeMidpointsMap(mesh);
        var pointToFacePointMap   = CreatePointToFacePointMap(mesh);

        return(mesh.points.Select((p, i) =>
        {
            var midPoint = pointsToEdgePointsMap[i];
            var facePoint = pointToFacePointMap[i];
            var r = Vector3.zero;
            var f = Vector3.zero;
            r = midPoint.Aggregate(r, (current, point) => current + point);
            f = facePoint.Aggregate(f, (current, point) => current + point);
            var n = midPoint.Count;
            r /= n;
            f /= n;
            return (f + 2 * r + (n - 3) * p) / n;
        }).ToList());
    }
コード例 #15
0
    // Creating a dictionary mapping from new points to their corresponding face points
    private static Dictionary <int, List <Vector3> > CreatePointToFacePointMap(CCMeshData mesh)
    {
        Dictionary <int, List <Vector3> > pointToFacePointMap = new Dictionary <int, List <Vector3> >();

        for (var i = 0; i < mesh.faces.Count; i++)
        {
            var face = mesh.faces[i];
            for (var j = 0; j < 4; j++)
            {
                var p = (int)face[j];
                if (!pointToFacePointMap.ContainsKey(p))
                {
                    pointToFacePointMap[p] = new List <Vector3>();
                }

                pointToFacePointMap[p].Add(mesh.facePoints[i]);
            }
        }

        return(pointToFacePointMap);
    }
コード例 #16
0
    // Returns a list of "edge points" for the given CCMeshData, as described in the Catmull-Clark algorithm
    public static List <Vector3> GetEdgePoints(CCMeshData mesh)
    {
        List <Vector3> edgePoints = new List <Vector3>();

        for (int i = 0; i < mesh.edges.Count; i++)
        {
            Vector3 edgePoint = mesh.points[(int)mesh.edges[i][0]] +
                                mesh.points[(int)mesh.edges[i][1]] +
                                mesh.facePoints[(int)mesh.edges[i][2]];

            if (mesh.edges[i][3] != -1)
            {
                edgePoint += mesh.facePoints[(int)mesh.edges[i][3]];
                edgePoint /= 4;
            }
            else
            {
                edgePoint /= 3;
            }
            edgePoints.Add(edgePoint);
        }
        return(edgePoints);
    }
コード例 #17
0
ファイル: CatmullClark.cs プロジェクト: damebrown/CG_ex3
    // Returns a list of all edges in the mesh defined by given points and faces.
    // Each edge is represented by Vector4(p1, p2, f1, f2)
    // p1, p2 are the edge vertices
    // f1, f2 are faces incident to the edge. If the edge belongs to one face only, f2 is -1
    public static List <Vector4> GetEdges(CCMeshData mesh)
    {
        List <Vector4> edges = new List <Vector4>();
        Dictionary <Vector3, Vector4> dict = new Dictionary <Vector3, Vector4>();

        for (int i = 0; i < mesh.faces.Count; ++i)
        {
            Vector3 place;
            for (int j = 0; j < 3; ++j)
            {
                place = (mesh.points[(int)mesh.faces[i][j]]) + (mesh.points[(int)mesh.faces[i][j + 1]]);
                if (dict.ContainsKey(place))
                {
                    dict[place] = new Vector4(dict[place][0], dict[place][1], dict[place][2], i);
                }
                else
                {
                    dict.Add(place, new Vector4(mesh.faces[i][j], mesh.faces[i][j + 1], i, -1));
                }
            }
            place = mesh.points[(int)mesh.faces[i][3]] + mesh.points[(int)mesh.faces[i][0]];
            if (dict.ContainsKey(place))
            {
                dict[place] = new Vector4(dict[place][0], dict[place][1], dict[place][2], i);
            }
            else
            {
                dict.Add(place, new Vector4(mesh.faces[i][3], mesh.faces[i][0], i, -1));
            }
        }
        foreach (Vector4 value in dict.Values)
        {
            edges.Add(value);
        }
        return(edges);
    }
コード例 #18
0
    // Returns a QuadMeshData representing the input mesh after one iteration of Catmull-Clark subdivision.
    public static QuadMeshData Subdivide(QuadMeshData quadMeshData)
    {
        // Create and initialize a CCMeshData corresponding to the given QuadMeshData
        CCMeshData meshData = new CCMeshData();

        meshData.points     = quadMeshData.vertices;
        meshData.faces      = quadMeshData.quads;
        meshData.edges      = GetEdges(meshData);
        meshData.facePoints = GetFacePoints(meshData);
        meshData.edgePoints = GetEdgePoints(meshData);
        meshData.newPoints  = GetNewPoints(meshData);



        // Combine facePoints, edgePoints and newPoints into a subdivided QuadMeshData

        // Your implementation here...


        var quads     = new List <Vector4>();
        var vertices  = new List <Vector3>();
        var vertToIdx = getPointDict(meshData, vertices);
        var t         = edges_dict(meshData);

        for (int i = 0; i < meshData.facePoints.Count; i++)
        {
            var fp     = vertToIdx[meshData.facePoints[i]];
            var points = meshData.faces[i];

            for (int p = 0; p < 4; p++)
            {
                var np                 = vertToIdx[meshData.newPoints[(int)points[p]]];
                var next_point         = (int)points[(p + 1) % 4];
                var original_point_cur = (int)points[p];
                var key1               = new Vector2(i, original_point_cur);
                var key2               = new Vector2(i, next_point);
                var cur_original_edges = t[key1];
                var next_edges         = t[key2];
                int right              = 0;
                for (int idx1 = 0; idx1 < cur_original_edges.Count; idx1++)
                {
                    for (int idx2 = 0; idx2 < next_edges.Count; idx2++)
                    {
                        if (cur_original_edges[idx1] == next_edges[idx2])
                        {
                            right = idx1;
                            break;
                        }
                    }
                }

                var quad = new Vector4(fp, vertToIdx[meshData.edgePoints[(int)cur_original_edges[(right + 1) % 2]]], np,
                                       vertToIdx[meshData.edgePoints[(int)cur_original_edges[right % 2]]]);

                quads.Add(quad);
            }
        }


        return(new QuadMeshData(vertices, quads));
    }
コード例 #19
0
 // Returns a list of "face points" for the given CCMeshData, as described in the Catmull-Clark algorithm
 public static List <Vector3> GetFacePoints(CCMeshData mesh)
 {
     return(mesh.faces.Select(face => (mesh.points[(int)face[0]] + mesh.points[(int)face[1]] +
                                       mesh.points[(int)face[2]] + mesh.points[(int)face[3]]) / 4).ToList());
 }
コード例 #20
0
ファイル: CatmullClark.cs プロジェクト: damebrown/CG_ex3
    // Returns a QuadMeshData representing the input mesh after one iteration of Catmull-Clark subdivision.
    public static QuadMeshData Subdivide(QuadMeshData quadMeshData)
    {
        // Create and initialize a CCMeshData corresponding to the given QuadMeshData
        CCMeshData meshData = new CCMeshData();

        meshData.points     = quadMeshData.vertices;
        meshData.faces      = quadMeshData.quads;
        meshData.edges      = GetEdges(meshData);
        meshData.facePoints = GetFacePoints(meshData);
        meshData.edgePoints = GetEdgePoints(meshData);
        meshData.newPoints  = GetNewPoints(meshData);
        List <List <int> > faceEdges = new List <List <int> >();

        for (int i = 0; i < meshData.faces.Count; ++i)
        {
            faceEdges.Add(new List <int>());
        }

        for (int i = 0; i < meshData.edges.Count; ++i)
        {
            faceEdges[(int)meshData.edges[i][2]].Add(i);
            faceEdges[(int)meshData.edges[i][3]].Add(i);
        }
        List <List <Vector2> > faceEdgePoints = new List <List <Vector2> >();

        for (int i = 0; i < faceEdges.Count; ++i)
        {
            faceEdgePoints.Add(new List <Vector2>());
            for (int j = 0; j < 4; ++j)
            {
                if (i == meshData.edges[faceEdges[i][j]][2])
                {
                    faceEdgePoints[i].Add(new Vector2(meshData.edges[faceEdges[i][j]][0], meshData.edges[faceEdges[i][j]][1]));
                }
                else
                {
                    faceEdgePoints[i].Add(new Vector2(meshData.edges[faceEdges[i][j]][1], meshData.edges[faceEdges[i][j]][0]));
                }
            }
        }
        List <Vector3> newPoints      = meshData.facePoints.Concat(meshData.edgePoints).Concat(meshData.newPoints).ToList();
        int            edgePointStart = meshData.facePoints.Count;
        int            newPointStart  = edgePointStart + meshData.edgePoints.Count;
        List <Vector4> newFaces       = new List <Vector4>();

        for (int i = 0; i < faceEdges.Count; ++i)
        {
            for (int j = 0; j < 3; ++j)
            {
                for (int k = j + 1; k < 4; ++k)
                {
                    if (faceEdgePoints[i][j][0] == faceEdgePoints[i][k][1])
                    {
                        newFaces.Add(new Vector4(i, faceEdges[i][k] + edgePointStart, faceEdgePoints[i][j][0] + newPointStart, faceEdges[i][j] + edgePointStart));
                    }
                    else if (faceEdgePoints[i][j][1] == faceEdgePoints[i][k][0])
                    {
                        newFaces.Add(new Vector4(i, faceEdges[i][j] + edgePointStart, faceEdgePoints[i][j][1] + newPointStart, faceEdges[i][k] + edgePointStart));
                    }
                }
            }
        }
        return(new QuadMeshData(newPoints, newFaces));
    }