Exemplo n.º 1
0
    private void SetLinks(GParticle parent, GParticle baby)
    {
        OrderNeighbors(parent);

        int firstIndex;

        if (parameters.longestAxis)
        {
            firstIndex = FindLongestAxis(parent);
        }
        else
        {
            firstIndex = FindShortestAxis(parent);
        }

        List <int> originalLinks = Rotate(parent.links, firstIndex);

        for (int i = 0; i <= originalLinks.Count / 2; i++)
        {
            baby.addLink(originalLinks[i]);
            cells[originalLinks[i]].addLink(baby.index);

            if (i != 0 && i != originalLinks.Count / 2)
            {
                parent.removeLink(originalLinks[i]);
                cells[originalLinks[i]].removeLink(parent.index);
            }
        }

        parent.addLink(baby.index);
        baby.addLink(parent.index);
    }
Exemplo n.º 2
0
    private void AddBulgeForce(GParticle p)
    {
        float bulgeDistance = 0;
        float thetaL, thetaD, thetaC, radicand;

        for (int i = 0; i < p.links.Count; i++)
        {
            Vector3 d = cells[p.links[i]].position - p.position;
            thetaL = Mathf.Acos(Vector3.Dot(d, p.normal) / d.magnitude);
            thetaD = Mathf.Asin(d.magnitude * Mathf.Sin(thetaL) / parameters.springLength);
            thetaC = Mathf.PI - thetaD - thetaL;

            if (float.IsNaN(thetaC) || float.IsInfinity(thetaC))
            {
                continue;
            }

            radicand = Mathf.Pow(parameters.springLength, 2f) + d.sqrMagnitude -
                       2.0f * d.magnitude * parameters.springLength * Mathf.Cos(thetaC);

            if (radicand < 0.0)
            {
                radicand = 0;
            }

            bulgeDistance += Mathf.Sqrt(radicand);
        }

        bulgeDistance /= p.links.Count;

        p.delta += p.normal * bulgeDistance * parameters.bulgeFactor;
    }
Exemplo n.º 3
0
    private void CalculateNormal(GParticle p)
    {
        OrderNeighbors(p);

        tmpNormal = Vector3.zero;

        for (int i = 0; i < p.links.Count; i++)
        {
            Vector3 c = cells[p.links[i]].position;
            Vector3 d = cells[p.links[(i + 1) % p.links.Count]].position;
            tmpNormal += Vector3.Cross(d, c);
        }

        // area = newNormal.squaredNorm();
        tmpNormal = tmpNormal.normalized;

        if (orientation(
                p.position,
                cells[p.links[0]].position,
                cells[p.links[1]].position) < 0)
        {
            p.normal = tmpNormal;
        }
        else
        {
            p.normal = -tmpNormal;
            p.links.Reverse();
        }
    }
Exemplo n.º 4
0
    private void AddPlanarForce(GParticle p)
    {
        Vector3 planarTarget = Vector3.zero;

        for (int i = 0; i < p.links.Count; ++i)
        {
            planarTarget += cells[p.links[i]].position;
        }
        planarTarget /= p.links.Count;
        planarTarget  = planarTarget - p.position;

        p.curvature = -1.0f * planarTarget.magnitude *
                      Vector3.Dot(p.normal, planarTarget.normalized);

        p.delta += planarTarget * parameters.planarFactor;
    }
Exemplo n.º 5
0
    private void AddSpringForce(GParticle p)
    {
        Vector3 target = Vector3.zero;

        foreach (var l in p.links)
        {
            Vector3 d = cells[l].position - p.position;
            d.Normalize();
            d      *= parameters.springLength;
            target += d;
        }

        target  /= p.links.Count;
        target  *= parameters.springLength;
        p.delta += target * parameters.springFactor;
    }
Exemplo n.º 6
0
    private void AddCollisionForce()
    {
        _points.Clear();
        _nodes.Clear();

        for (int i = 0; i < cells.Count; i++)
        {
            var p = cells[i];
            _points.Add(new double[] { p.position.x, p.position.y, p.position.z });
            _nodes.Add(i);
        }

        KDTree <double, int> tree = new KDTree <double, int>(3, _points.ToArray(), _nodes.ToArray(), L2Norm);

        double radiusSquared = parameters.radius * parameters.radius;

        for (int i = 0; i < cells.Count; i++)
        {
            GParticle p = cells[i];
            p.collisions = 0;

            var rsquared = parameters.radius * parameters.radius;

            Tuple <double[], int>[] neighbors = tree.NearestNeighbors(new double[] { p.position.x, p.position.y, p.position.z }, (int)parameters.maxNeighbors);

            foreach (var neighbor in neighbors)
            {
                GParticle q            = cells[neighbor.Item2];
                Vector3   displacement = p.position - q.position;

                float distanceSquared = displacement.x * displacement.x +
                                        displacement.y * displacement.y +
                                        displacement.z * displacement.z;

                if ((i != neighbor.Item2) && (!p.connectedTo(neighbor.Item2)))
                {
                    displacement.Normalize();
                    displacement *= (rsquared - distanceSquared) / rsquared; // TODO sqrt here? NGS what is this even ????

                    p.delta += displacement * parameters.collisionFactor;
                    p.collisions++;
                }
            }
        }
    }
Exemplo n.º 7
0
    private void AddCollisionBruteForce()
    {
        var tree = new KdTree <float, int>(3, new FloatMath());

        for (int i = 0; i < cells.Count; i++)
        {
            tree.Add(new[] { cells[i].position.x, cells[i].position.y, cells[i].position.z }, i);
        }


        double radiusSquared = parameters.radius * parameters.radius;

        for (int i = 0; i < cells.Count; i++)
        {
            GParticle p = cells[i];
            p.collisions = 0;

            var rsquared = parameters.radius * parameters.radius;

            var neighbors = tree.GetNearestNeighbours(new[] { cells[i].position.x, cells[i].position.y, cells[i].position.z },
                                                      (int)parameters.maxNeighbors);

            for (int j = 0; j < neighbors.Length; j++)
            {
                GParticle q            = cells[neighbors[j].Value];
                Vector3   displacement = p.position - q.position;

                if (displacement.magnitude < parameters.radius)
                {
                    float distanceSquared = displacement.x * displacement.x +
                                            displacement.y * displacement.y +
                                            displacement.z * displacement.z;

                    if ((i != j) && (!p.connectedTo(j)))
                    {
                        displacement.Normalize();
                        displacement *= (rsquared - distanceSquared) / rsquared; // TODO sqrt here? NGS what is this even ????

                        p.delta += displacement * parameters.collisionFactor;
                        p.collisions++;
                    }
                }
            }
        }
    }
Exemplo n.º 8
0
    private void OrderNeighbors(GParticle p)
    {
        if (p.links.Count < 3)
        {
            return;
        }

        List <int> orderedLinks = new List <int>();

        orderedLinks.Add(p.links[0]);
        orderedLinks.Add(GetNext(p, p.links[0]));

        for (int i = 2; i < p.links.Count; i++)
        {
            orderedLinks.Add(GetNext(p, orderedLinks[i - 2], orderedLinks[i - 1]));
        }

        p.links = orderedLinks;
    }
Exemplo n.º 9
0
    private int GetNext(GParticle p, int previousIndex, int currentIndex)
    {
        GParticle current = cells[currentIndex];

        for (int i = 0; i < p.links.Count; i++)
        {
            for (int j = 0; j < current.links.Count; j++)
            {
                if ((p.links[i] == current.links[j]) &&
                    (p.links[i] != previousIndex) &&
                    (p.links[i] != currentIndex))
                {
                    return(p.links[i]);
                }
            }
        }

        return(-1);
    }
Exemplo n.º 10
0
    private void GenerateCells(Mesh m)
    {
        cells = new List <GParticle>();

        for (int i = 0; i < m.vertexCount; ++i)
        {
            GParticle p = new GParticle();
            p.position = m.vertices[i];
            p.normal   = m.normals[i].normalized;
            p.index    = i;
            cells.Add(p);
        }

        for (int i = 0; i < m.GetIndexCount(0); i += 3)
        {
            ConnectCell(m.GetIndices(0)[i], m.GetIndices(0)[i + 1]);
            ConnectCell(m.GetIndices(0)[i], m.GetIndices(0)[i + 2]);
            ConnectCell(m.GetIndices(0)[i + 1], m.GetIndices(0)[i + 2]);
        }
    }
Exemplo n.º 11
0
    private int FindLongestAxis(GParticle p)
    {
        List <int> links = p.links;

        float maxLength    = float.MaxValue;
        int   longestIndex = -1;

        for (int i = 0; i < links.Count; i++)
        {
            float distance = (p.position - cells[links[i]].position).magnitude;
            int   opposite = (i + (links.Count / 2)) % links.Count;
            distance += (p.position - cells[links[opposite]].position).magnitude;
            if (distance > maxLength || i == 0)
            {
                maxLength    = distance;
                longestIndex = (int)i;
            }
        }
        return(longestIndex);
    }
Exemplo n.º 12
0
    private int FindShortestAxis(GParticle p)
    {
        List <int> links = p.links;

        float minLength     = 0;
        int   shortestIndex = -1;

        for (int i = 0; i < links.Count; i++)
        {
            float distance = (p.position - cells[links[i]].position).magnitude;
            int   opposite = (i + (links.Count / 2)) % links.Count;
            distance += (p.position - cells[links[opposite]].position).magnitude;
            if (distance < minLength || i == 0)
            {
                minLength     = distance;
                shortestIndex = (int)i;
            }
        }
        return(shortestIndex);
    }
Exemplo n.º 13
0
    private void Split(GParticle p)
    {
        int index = (int)cells.Count;

        cells.Add(new GParticle());
        GParticle baby = cells[index];

        baby.normal   = p.normal;
        baby.position = p.position;
        baby.index    = index;
        baby.food     = 1;
        SetLinks(p, baby);

        SetPositions(p, baby);

        CalculateNormal(p);
        CalculateNormal(baby);

        baby.food = 0;
        p.food    = 0;
    }
Exemplo n.º 14
0
    public Mesh GetMesh()
    {
        //Profiler.BeginSample("GetMesh");

        Mesh m = new Mesh();

        List <Vector3> verts   = new List <Vector3>();
        List <Vector3> normals = new List <Vector3>();
        List <Color>   colors  = new List <Color>();
        List <int>     ints    = new List <int>();

        for (int i = 0; i < cells.Count; ++i)
        {
            verts.Add(cells[i].position);
            colors.Add(Color.white * (cells[i].curvature + 5.0f) * 20.0f);
            normals.Add(-cells[i].normal);
        }

        m.SetVertices(verts);
        m.SetColors(colors);
        m.SetNormals(normals);

        for (int i = 0; i < cells.Count; ++i)
        {
            GParticle p = cells[i];

            int numLinks = p.links.Count;
            for (int ii = 0; ii < numLinks; ++ii)
            {
                ints.Add(p.index);
                ints.Add(p.links[ii]);
                ints.Add(p.links[(ii + 1) % numLinks]);
            }
        }

        m.SetIndices(ints.ToArray(), MeshTopology.Triangles, 0);
        //Profiler.EndSample();

        return(m);
    }
Exemplo n.º 15
0
    private void SetPositions(GParticle parent, GParticle baby)
    {
        Vector3 babyAverage = parent.position;

        for (int i = 0; i < baby.links.Count; ++i)
        {
            babyAverage += cells[baby.links[i]].position;
        }

        babyAverage /= baby.links.Count + 1;

        Vector3 parentAverage = parent.position;

        for (int i = 0; i < parent.links.Count; ++i)
        {
            parentAverage += cells[parent.links[i]].position;
        }
        parentAverage /= parent.links.Count + 1;

        // set positions
        baby.position   = babyAverage;
        parent.position = parentAverage;
    }
Exemplo n.º 16
0
 private int GetNext(GParticle p, int i)
 {
     return(GetNext(p, i, i));
 }