Ejemplo n.º 1
0
    private static void BuildNeighborsLists(AdjacencySets adjSets, List <Vector3> neighbors,
                                            List <int> neighborIndices, int i, Vector3[] vertices)
    {
        HashSet <int> aSet = adjSets.GetAdjacencySet(i);

        foreach (int index in aSet)
        {
            if (i != index)
            {
                neighbors.Add(vertices[index]);
                neighborIndices.Add(index);
            }
        }
    }
Ejemplo n.º 2
0
    public static void AdjSetsHCSmoother(Mesh mesh, AdjacencySets adjacencySets)
    {
        Vector3[] ov         = mesh.vertices; // original vertices
        Vector3[] wv         = mesh.vertices; // will contain the Laplacian smoothing
        Vector3[] bv         = new Vector3[mesh.vertices.Length];
        bool[]    canBeMoved = new bool[mesh.vertices.Length];

        List <Vector3> neighbors       = new List <Vector3>();
        List <int>     neighborIndices = new List <int>();

        for (int i = 0; i < wv.Length; i++)
        {
            neighbors.Clear();                                                  // must exist but be empty for each new vertex
            neighborIndices.Clear();
            BuildNeighborsLists(adjacencySets, neighbors, neighborIndices, i, ov);

            // True if the vertex is not on the edge of the mesh.
            canBeMoved[i] = IsInsideVertex(neighbors, neighborIndices, adjacencySets);
            if (canBeMoved[i])
            {
                wv[i] = TrueAverageVertex(neighbors, ov[i]);
            }

            // Compute the differences
            bv[i] = wv[i] - ov[i];
        }

        // We let the first loop complete because bv must be filled for the next step
        Vector3 average;
        Vector3 move;

        for (int i = 0; i < bv.Length; i++)
        {
            // We can't reuse the same neighbor list, because we get it from bv this time
            neighbors.Clear();
            neighborIndices.Clear();
            BuildNeighborsLists(adjacencySets, neighbors, neighborIndices, i, bv);
            average = AverageOfNeighbors(neighbors);

            // Final computation
            if (canBeMoved[i])
            {
                move   = BETA * bv[i] + ONE_MINUS_BETA * average;
                wv[i] += HC_CORRECT * move;
            }
        }
        mesh.vertices = wv;
    }
Ejemplo n.º 3
0
    public static void AdjSetsSmoother(MeshData mData, AdjacencySets adjacencySets)
    {
        Vector3[]      vertices        = mData.vertices;
        Vector3[]      ov              = mData.vertices; // original vertices
        List <Vector3> neighbors       = new List <Vector3>();
        List <int>     neighborIndices = new List <int>();

        for (int i = 0; i < vertices.Length; i++)
        {
            neighbors.Clear();                                                  // must exist but be empty for each new vertex
            neighborIndices.Clear();
            BuildNeighborsLists(adjacencySets, neighbors, neighborIndices, i, ov);
            vertices[i] = TrueAverageVertex(neighbors, ov[i]);
        }
        mData.vertices = vertices;
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Creates the surface objects.
    /// </summary>
    /// <param name='voxels'>
    /// Voxels, i.e. the scalar field used to compute the surface.
    /// </param>
    /// <param name='threshold'>
    /// The threshold on which the isosurface is based.
    /// </param>
    /// <param name='delta'>
    /// Delta parameter from the grid, basically the size of each cell.
    /// </param>
    /// <param name='origin'>
    /// Origin of the grid.
    /// </param>
    /// <param name='colors'>
    /// Colors. Kept from previous implementation, but doesn't do anything here. I'm only
    /// keeping it because I'm not sure what it was used for. --- Alexandre
    /// </param>
    /// <param name='tag'>
    /// Tag for the objects to be created.
    /// </param>
    /// <param name='electro'>
    /// True if this is an electrostatic field isosurface.
    /// </param>
    public static void CreateSurfaceObjects(float[,,] voxels, float threshold, Vector3 delta, Vector3 origin,
                                            Color[] colors, string tag = "SurfaceManager", bool electro = false)
    {
        ELECTRO = electro;
        Debug.Log(ELECTRO.ToString());
        if (ELECTRO)
        {
            ReadDX readDX = UI.GUIMoleculeController.readdx;
            origin = readDX.GetOrigin();
            delta  = readDX.GetDelta();
        }

        InitGenMesh(voxels, threshold, delta, origin, tag);
        SetDims();

        float    bMCTime = Time.realtimeSinceStartup;
        MeshData mData   = MarchingCubes.CreateMesh(VOXELS, 0, XDIM, 0, YDIM, 0, ZDIM);

        Debug.Log("Entire surface contains " + mData.vertices.Length.ToString() + " vertices.");
        float elapsed = 10f * (Time.realtimeSinceStartup - bMCTime);

        Debug.Log("GenerateMesh::MarchingCubes time: " + elapsed.ToString());
        OffsetVertices(mData);

        float         bSmooth       = Time.realtimeSinceStartup;
        AdjacencySets adjacencySets = new AdjacencySets(mData.triangles.Length);

        adjacencySets.AddAllTriangles(mData.triangles);
        SmoothFilter.AdjSetsSmoother(mData, adjacencySets);
        elapsed = Time.realtimeSinceStartup - bSmooth;
        Debug.Log("Smoothing time: " + elapsed.ToString());

        ProperlyCalculateNormals(mData);

        // Necessary for electrostatic fields isosurfaces
        Debug.Log(threshold.ToString());
        if (threshold < 0)
        {
            FlipTriangles(mData);
        }

        Splitting   splitting = new Splitting();
        List <Mesh> meshes    = splitting.Split(mData);

        CreateSurfaceObjects(meshes);
    }
Ejemplo n.º 5
0
    private static bool IsInsideVertex(List <Vector3> neighbors,
                                       List <int> nIndices, AdjacencySets aSets)
    {
        int           nbNeighbors;      // number of neighbors that each neighbor possesses
        HashSet <int> aSet;

        // First we iterate over every neighbor of the "central" vertex we consider
        for (int nIndex = 0; nIndex < neighbors.Count; nIndex++)
        {
            // We then get the adjacency set containing *its* neighbors
            aSet        = aSets.GetAdjacencySet(nIndices[nIndex]);
            nbNeighbors = 0;

            // We now iterate over this set. If any value in it is also in the nIndices list,
            // i.e. in the list of neighbors of our "central" vertex, we increment the number
            // of neighbors.
            foreach (int a in aSet)
            {
                if (nIndices.Contains(a))
                {
                    nbNeighbors++;
                }
            }

            // If this number is less than two, this means one of the neighbors of the central
            // vertex has less than two neighbors that are also a neighbor of the central vertex.
            // In other words, the central vertex is on an edge of the mesh.
            if (nbNeighbors < 2)
            {
                return(false);
            }
        }

        // If the function has never returned false, then the vertex is not on an edge.
        // It can be moved.
        return(true);
    }