internal void SetOffsets()
    {
        s_SeOffsets.Auto();
        for (int j = 0; j < gravGridDimensions; j++)
        {
            int   yOffset = (j + mStartWorldY) - rootCoord.y;
            float s       = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;
            for (int i = 0; i < gravGridDimensions; i++)
            {
                int      x       = mod((mStartWorldX + i), gravGridDimensions);
                int      y       = mod((mStartWorldY + j), gravGridDimensions);
                GravNode gn      = gravGrid[x, y];
                int      index   = gn.m_Index;
                int      xOffset = (i + mStartWorldX) - rootCoord.x;
                float    t       = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;

                offsets[index] = new float2(t, s);
            }
        }
        //var SetOffsetsJob = new GravNode.SetOffsets()
        //{
        //    coordinate = coordinates,
        //    sectorOffsets = offsets,
        //    dimensions = new int2(mHorizontalParticles, mVerticalParticles),
        //    worldStart = new int2(mStartWorldX, mStartWorldY),
        //    sectorStart = sector
        //};
        //SetOffsetsJob.Schedule(coordinates.Length, 64).Complete();
    }
Example #2
0
 public int FindLinkIndex(GravNode gn2)
 {
     for (int i = 0; i < m_Links.Count; i++)
     {
         if (m_Links[i].m_Gn2.m_Index == gn2.m_Index)
         {
             return(m_Links[i].m_Index);
         }
     }
     return(-1);
 }
    private void RemoveConnection(GravNode gn1, GravNode gn2)
    {
        s_RemoveLinkCreateIP.Begin();
        int indexResult = gn1.FindLinkIndex(gn2);

        if (indexResult == -1)
        {
            Debug.LogError("Link not found");
            return;
        }
        s_RemoveLinkCreateIP.End();

        connections[indexResult].BreakLink(m_GravMesh);
        availableConnectionIndex.Enqueue(indexResult);
    }
    internal void MakeLink(GravNode gn1, GravNode gn2, bool draw, GravMesh gravMesh, float thickness, float spacing)
    {
        m_Gn1 = gn1;
        m_Gn2 = gn2;
        m_GravNode1PosIndex = gn1.m_Index;
        m_GravNode2PosIndex = gn2.m_Index;
        m_RestDistance      = spacing;

        gn1.m_Links.Add(this);

        gn1.neighborIndiciesList.Add(gn2.m_Index);
        gn1.restDistancesList.Add(m_RestDistance);

        gn2.neighborIndiciesList.Add(gn1.m_Index);
        gn2.restDistancesList.Add(m_RestDistance);

        m_Draw      = draw;
        m_Thickness = thickness;

        if (draw)
        {
            if (gn1.availibleVertexPositions.Count == 0)
            {
                Debug.LogError("No more vertices are available for rendering this connection");
            }

            m_GravNode1VertexStart = gn1.availibleVertexPositions.Dequeue();

            if (gn2.availibleVertexPositions.Count == 0)
            {
                Debug.LogError("No more vertices are available for rendering this connection");
            }

            m_GravNode2VertexStart = gn2.availibleVertexPositions.Dequeue();
            m_TrianglesIndex       = gravMesh.AddPair(m_GravNode1VertexStart, m_GravNode2VertexStart);
        }

        gn1.m_Connections++;
        gn2.m_Connections++;
    }
    public void AddAndSetupConnectionAtNextIndex(GravNode gn1, GravNode gn2, bool draw, GravMesh gravMesh)
    {
        if (availableConnectionIndex.Count == 0)
        {
            Debug.LogError("There are no available connections.");
        }
        s_CreateNewLink.Begin();
        int index = availableConnectionIndex.Dequeue();

        //We're not going to update the thickness data as to preserve the sector location.
        connections[index].MakeLink(gn1, gn2, draw, gravMesh, 0, spacing);
        s_CreateNewLink.End();

        gn1Index[index]              = connections[index].m_GravNode1PosIndex;
        gn2Index[index]              = connections[index].m_GravNode2PosIndex;
        drawables[index]             = connections[index].m_Draw;
        gn1VertexStartIndices[index] = connections[index].m_GravNode1VertexStart;
        gn2VertexStartIndices[index] = connections[index].m_GravNode2VertexStart;

        int gn1I = gn1.m_Index;
        int gn2I = gn2.m_Index;

        nodeNumConnections[gn1I] = gn1.m_Connections;
        nodeNumConnections[gn2I] = gn2.m_Connections;
        int connectionsStart = startConnectionsIndex[gn1I];

        for (int i = 0; i < gn1.m_Connections; i++)
        {
            allNodeConnections[i + connectionsStart] = gn1.neighborIndiciesList[i];
            allRestsDistances[i + connectionsStart]  = gn1.restDistancesList[i];
        }

        connectionsStart = startConnectionsIndex[gn2I];
        for (int i = 0; i < gn2.m_Connections; i++)
        {
            allNodeConnections[i + connectionsStart] = gn2.neighborIndiciesList[i];
            allRestsDistances[i + connectionsStart]  = gn2.restDistancesList[i];
        }
    }
    public void ConfigureNewStartAndEndNodes(
        GravNode break1,
        GravNode break2,
        GravNode connect1,
        GravNode connect2,
        GravNode newStart,
        GravNode newEnd,
        GravNode newMid,
        int row, int start, int max)
    {
        s_AddConnections.Begin();
        RemoveConnection(break1, break2);
        AddAndSetupConnectionAtNextIndex(connect1, connect2, true, m_GravMesh);
        s_AddConnections.End();

        s_SetGravNodeConnectionProperties.Begin();
        if (row != start && row != start + max - 1)
        {
            int midIndex = newMid.m_Index;
            newMid.SetMoveable(true);
            moveables[midIndex] = true;
        }

        int newStartXIndex = newStart.m_Index;

        affected[newStartXIndex]  = false;
        moveables[newStartXIndex] = false;
        newStart.SetMoveable(false);

        int newEndXINdex = newEnd.m_Index;

        affected[newEndXINdex]  = false;
        moveables[newEndXINdex] = false;
        newEnd.SetMoveable(false);

        s_SetGravNodeConnectionProperties.End();
    }
    void Start()
    {
        gravGridCam           = Camera.main;
        fixedDeltaTimeSeconds = (float)fixedDeltaTime / 1000.0f;
        gravGrid  = new GravNode[gravGridDimensions, gravGridDimensions];
        gravNodes = new List <GravNode>(gravGridDimensions * gravGridDimensions);
        float gridSizeWorld = gravGridDimensions * spacing;

        m_GravMesh = new GravMesh(new Vector3(gridSizeWorld, gridSizeWorld, 0.5f), gridSizeWorld, GetComponent <MeshFilter>());

        m_MeshMatcher = new MeshMatcher(gravGridDimensions / sectorSize, parentLayer, spacing, gravGridDimensions);
        m_MeshMatcher.SetAdjacentNodes(rootCoord);

        availableConnectionIndex = new Queue <int>();
        offsets                = new NativeArray <float2>(gravGridDimensions * gravGridDimensions, Allocator.Persistent);
        coordinates            = new NativeArray <int2>(gravGridDimensions * gravGridDimensions, Allocator.Persistent);
        rootCoord              = new int2(startingRootCoordinate.x, startingRootCoordinate.y);
        colliderTransformArray = new TransformAccessArray(gravGridDimensions * gravGridDimensions);

        for (int j = 0, index = 0; j < gravGridDimensions; ++j)
        {
            int   yOffset = (j + mStartWorldY) - rootCoord.y;
            float s       = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;


            for (int i = 0; i < gravGridDimensions; ++i, index++)
            {
                int   xOffset = (i + mStartWorldX) - rootCoord.x;
                float t       = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;

                Vector3 position         = new Vector3(i * spacing, j * spacing, 0);
                int     vertexStartIndex = m_GravMesh.AddNode();
                offsets[index]     = new float2(t, s);
                coordinates[index] = new int2(i, j);

                var gn = new GravNode(position, spacing, index, transform, vertexStartIndex, gameObject.layer);
                colliderTransformArray.Add(gn.gravNodeColliderParent.transform);
                gn.AddForce          = ApplyForce;
                gn.SetTargetLocation = SetTargetLocation;
                gn.Return            = SetTargetToReturnPosition;
                gn.GetNodePosition   = GetNodePosition;
                gn.GetReturnPosition = GetReturnPosition;
                gravGrid[i, j]       = gn;
                gravNodes.Add(gn);
            }
        }

        nodeNumConnections    = new NativeArray <int>(gravNodes.Count, Allocator.Persistent);
        startConnectionsIndex = new NativeArray <int>(gravNodes.Count, Allocator.Persistent);
        allNodeConnections    = new NativeArray <int>(gravNodes.Count * MAX_CONNECTIONS, Allocator.Persistent);
        allRestsDistances     = new NativeArray <float>(gravNodes.Count * MAX_CONNECTIONS, Allocator.Persistent);

        targetPositions     = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        returnPositions     = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        affected            = new NativeArray <bool>(gravNodes.Count, Allocator.Persistent);
        prevPositions       = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        positions           = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        newPositions        = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        accelerations       = new NativeArray <float3>(gravNodes.Count, Allocator.Persistent);
        moveables           = new NativeArray <bool>(gravNodes.Count, Allocator.Persistent);
        forceUpdatePosition = new NativeArray <bool>(gravNodes.Count, Allocator.Persistent);

        for (int j = 0; j < gravNodes.Count; j++)
        {
            accelerations[j]   = gravNodes[j].m_Acceleration;
            prevPositions[j]   = gravNodes[j].m_PrevPosition;
            targetPositions[j] = gravNodes[j].m_TargetPosition;
            returnPositions[j] = gravNodes[j].m_ReturnPosition;
            affected[j]        = false;
            moveables[j]       = gravNodes[j].m_Moveable;
            positions[j]       = gravNodes[j].m_Position;
        }

        ResetConnections();
    }
    public void ShiftGrid(GridShiftDirection gridShiftDirection)
    {
        switch (gridShiftDirection)
        {
        case GridShiftDirection.Right:
        {
            int newStart     = mStartWorldX + 1;
            int oldEnd       = mod(mStartWorldX + gravGridDimensions - 1, gravGridDimensions);
            int newStartX    = mod(newStart, gravGridDimensions);
            int oldStart     = mod(mStartWorldX, gravGridDimensions);
            int newWorldXPos = mStartWorldX + gravGridDimensions;

            for (int j = 0; j < gravGridDimensions; j++)
            {
                int y = mod((mStartWorldY + j), gravGridDimensions);


                s_UpdateNodePosesOnShift.Begin();

                int   yOffset = (mStartWorldY + j) - rootCoord.y;
                int   xOffset = newWorldXPos - rootCoord.x;
                float t       = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;
                float s       = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;


                GravNode newStartGN       = gravGrid[newStartX, y];
                GravNode oldStartNewEndGN = gravGrid[oldStart, y];
                GravNode oldEndGN         = gravGrid[oldEnd, y];
                offsets[oldStartNewEndGN.m_Index]             = new float2(t, s);
                forceUpdatePosition[oldStartNewEndGN.m_Index] = true;

                ConfigureNewStartAndEndNodes(
                    oldStartNewEndGN, //break
                    newStartGN,       //break
                    oldEndGN,         // connect
                    oldStartNewEndGN, //connect
                    newStartGN,       //start
                    oldStartNewEndGN, //end
                    oldEndGN,         //middle
                    y, mStartWorldY, gravGridDimensions);
                s_UpdateNodePosesOnShift.End();
            }
            mStartWorldX = newStart;
            if (oldStart == startingRootCoordinate.x)         // sector is moving!!
            {
                SectorShift(new int2(gravGridDimensions, 0));
            }
            break;
        }

        case GridShiftDirection.Up:
        {
            int newStart     = mStartWorldY + 1;
            int oldEnd       = mod(mStartWorldY + gravGridDimensions - 1, gravGridDimensions);
            int newStartY    = mod(newStart, gravGridDimensions);
            int oldStart     = mod(mStartWorldY, gravGridDimensions);
            int newWorldYPos = mStartWorldY + gravGridDimensions;

            for (int j = 0; j < gravGridDimensions; j++)
            {
                s_UpdateNodePosesOnShift.Begin();

                int x = mod((mStartWorldX + j), gravGridDimensions);

                int yOffset = newWorldYPos - rootCoord.y;
                int xOffset = (j + mStartWorldX) - rootCoord.x;

                float t = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;
                float s = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;

                GravNode newStartGN       = gravGrid[x, newStartY];
                GravNode oldStartNewEndGN = gravGrid[x, oldStart];
                GravNode oldEndGN         = gravGrid[x, oldEnd];
                offsets[oldStartNewEndGN.m_Index]             = new float2(t, s);
                forceUpdatePosition[oldStartNewEndGN.m_Index] = true;

                ConfigureNewStartAndEndNodes(
                    oldStartNewEndGN, //break
                    newStartGN,       //break
                    oldEndGN,         // connect
                    oldStartNewEndGN, //connect
                    newStartGN,       //start
                    oldStartNewEndGN, //end
                    oldEndGN,         //middle
                    x, mStartWorldX, gravGridDimensions);
                s_UpdateNodePosesOnShift.End();
            }
            mStartWorldY = newStart;
            if (oldStart == startingRootCoordinate.y)         // sector is moving!!
            {
                SectorShift(new int2(0, gravGridDimensions));
            }

            break;
        }

        case GridShiftDirection.Left:
        {
            int newStart = mStartWorldX - 1;
            int oldStart = mod(mStartWorldX, gravGridDimensions);
            int oldEnd   = mod(mStartWorldX + gravGridDimensions - 1, gravGridDimensions);
            int newEnd   = mod(mStartWorldX + gravGridDimensions - 2, gravGridDimensions);

            for (int j = 0; j < gravGridDimensions; j++)
            {
                s_UpdateNodePosesOnShift.Begin();

                int y = mod((mStartWorldY + j), gravGridDimensions);

                int   yOffset = (j + mStartWorldY) - rootCoord.y;
                int   xOffset = newStart - rootCoord.x;
                float t       = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;
                float s       = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;


                GravNode oldStartGN       = gravGrid[oldStart, y];
                GravNode newEndGN         = gravGrid[newEnd, y];
                GravNode oldEndNewStartGN = gravGrid[oldEnd, y];
                offsets[oldEndNewStartGN.m_Index]             = new float2(t, s);
                forceUpdatePosition[oldEndNewStartGN.m_Index] = true;


                ConfigureNewStartAndEndNodes(
                    newEndGN,         //break
                    oldEndNewStartGN, //break
                    oldEndNewStartGN, // connect
                    oldStartGN,       //connect
                    oldEndNewStartGN, //start
                    newEndGN,         //end
                    oldStartGN,       //middle
                    y, mStartWorldY, gravGridDimensions);
                s_UpdateNodePosesOnShift.End();
            }
            mStartWorldX = newStart;
            if (oldEnd == startingRootCoordinate.x)         // sector is moving!!
            {
                SectorShift(new int2(-gravGridDimensions, 0));
            }
            break;
        }

        case GridShiftDirection.Down:
        {
            int newStart = mStartWorldY - 1;
            int oldStart = mod(mStartWorldY, gravGridDimensions);
            int oldEnd   = mod(mStartWorldY + gravGridDimensions - 1, gravGridDimensions);
            int newEnd   = mod(mStartWorldY + gravGridDimensions - 2, gravGridDimensions);

            for (int j = 0; j < gravGridDimensions; j++)
            {
                s_UpdateNodePosesOnShift.Begin();

                int x = mod((mStartWorldX + j), gravGridDimensions);

                int   yOffset = newStart - rootCoord.y;
                int   xOffset = (j + mStartWorldX) - rootCoord.x;
                float t       = ((float)xOffset / (float)gravGridDimensions + 1.0f) / 2.0f;
                float s       = ((float)yOffset / (float)gravGridDimensions + 1.0f) / 2.0f;

                GravNode oldStartGN       = gravGrid[x, oldStart];
                GravNode newEndGN         = gravGrid[x, newEnd];
                GravNode oldEndNewStartGN = gravGrid[x, oldEnd];
                offsets[oldEndNewStartGN.m_Index]             = new float2(t, s);
                forceUpdatePosition[oldEndNewStartGN.m_Index] = true;

                ConfigureNewStartAndEndNodes(
                    newEndGN,         //break
                    oldEndNewStartGN, //break
                    oldEndNewStartGN, // connect
                    oldStartGN,       //connect
                    oldEndNewStartGN, //start
                    newEndGN,         //end
                    oldStartGN,       //middle
                    x, mStartWorldX, gravGridDimensions);
                s_UpdateNodePosesOnShift.End();
            }
            mStartWorldY = newStart;
            if (oldEnd == startingRootCoordinate.y)         // sector is moving!!
            {
                SectorShift(new int2(0, -gravGridDimensions));
            }
            break;
        }

        default:
            break;
        }
    }
    public void AddConnection(GravNode gn1, GravNode gn2, bool draw, float thickness, GravMesh gravMesh)
    {
        Link l = new Link(gn1, gn2, draw, gravMesh, thickness, connections.Count, spacing);

        connections.Add(l);
    }
Example #10
0
    public void ResetConnections()
    {
        s_ResetConnections.Begin();
        connections.Clear();

        for (int i = 0; i < gravNodes.Count; i++)
        {
            gravNodes[i].m_Connections = 0;
            gravNodes[i].neighborIndiciesList.Clear();
            gravNodes[i].restDistancesList.Clear();
            gravNodes[i].stiffnessesList.Clear();
        }

        s_AddConnections.Begin();
        for (int j = 0; j < gravGridDimensions; j++)
        {
            int y = mod((mStartWorldY + j), gravGridDimensions);
            for (int i = 0; i < gravGridDimensions; i++)
            {
                int   x          = mod((mStartWorldX + i), gravGridDimensions);
                float thickcessX = lineWidth;
                float thickcessY = lineWidth;
                if (y % sectorSize == 0)
                {
                    thickcessX *= 3;
                }
                if (x % sectorSize == 0)
                {
                    thickcessY *= 3;
                }

                if (i < gravGridDimensions - 1)
                {
                    AddConnection(gravGrid[x, y], gravGrid[mod((x + 1), gravGridDimensions), y], true, thickcessX, m_GravMesh);
                }
                if (j < gravGridDimensions - 1)
                {
                    AddConnection(gravGrid[x, y], gravGrid[x, mod((y + 1), gravGridDimensions)], true, thickcessY, m_GravMesh);
                }
                //if (x < mHorizontalParticles - 1 && y < mVerticalParticles - 1) AddConnection(gravGrid[x, y], gravGrid[x + 1, y + 1], drawDiagonals, planeLinkStiffness, m_GravMesh);
                //if (x < mHorizontalParticles - 1 && y < mVerticalParticles - 1) AddConnection(gravGrid[x + 1, y], gravGrid[x, y + 1], drawDiagonals, planeLinkStiffness, m_GravMesh);
                //configure extended connections
                //if (x < mHorizontalParticles - 2) AddConnection(gravGrid[x, y], gravGrid[x + 2, y], drawDiagonals, planeLinkStiffness, m_GravMesh);
                //if (y < mVerticalParticles - 2) AddConnection(gravGrid[x, y], gravGrid[x, y + 2], drawDiagonals, planeLinkStiffness, m_GravMesh);
                //if (x < mHorizontalParticles - 2 && y < mVerticalParticles - 2) AddConnection(gravGrid[x, y], gravGrid[x + 2, y + 2], drawDiagonals, planeLinkStiffness, m_GravMesh);
                //if (x < mHorizontalParticles - 2 && y < mVerticalParticles - 2) AddConnection(gravGrid[x + 2, y], gravGrid[x, y + 2], drawDiagonals, planeLinkStiffness, m_GravMesh);

                if (x == mStartWorldX || y == mStartWorldY || x == mStartWorldX + gravGridDimensions - 1 || y == mStartWorldY + gravGridDimensions - 1)
                {
                    gravGrid[x, y].SetMoveable(false);
                }
                else
                {
                    gravGrid[x, y].SetMoveable(true);
                }
            }
        }
        s_AddConnections.End();

        if (!gn1Index.IsCreated)
        {
            gn1Index = new NativeArray <int>(connections.Count, Allocator.Persistent);
        }
        if (!gn2Index.IsCreated)
        {
            gn2Index = new NativeArray <int>(connections.Count, Allocator.Persistent);
        }
        if (!gn1VertexStartIndices.IsCreated)
        {
            gn1VertexStartIndices = new NativeArray <int>(connections.Count, Allocator.Persistent);
        }
        if (!gn2VertexStartIndices.IsCreated)
        {
            gn2VertexStartIndices = new NativeArray <int>(connections.Count, Allocator.Persistent);
        }
        if (!drawables.IsCreated)
        {
            drawables = new NativeArray <bool>(connections.Count, Allocator.Persistent);
        }
        if (!lineWidths.IsCreated)
        {
            lineWidths = new NativeArray <float>(connections.Count, Allocator.Persistent);
        }
        if (!baseLineWidths.IsCreated)
        {
            baseLineWidths = new NativeArray <float>(connections.Count, Allocator.Persistent);
        }


        s_ConstructuMesh.Begin();
        m_GravMesh.ConstructMesh();
        s_ConstructuMesh.End();

        s_SetConnectionProperties.Begin();
        for (int j = 0; j < connections.Count; j++)
        {
            gn1Index[j]              = connections[j].m_GravNode1PosIndex;
            gn2Index[j]              = connections[j].m_GravNode2PosIndex;
            drawables[j]             = connections[j].m_Draw;
            gn1VertexStartIndices[j] = connections[j].m_GravNode1VertexStart;
            gn2VertexStartIndices[j] = connections[j].m_GravNode2VertexStart;
            lineWidths[j]            = connections[j].m_Thickness;
            baseLineWidths[j]        = connections[j].m_Thickness;
        }
        s_SetConnectionProperties.End();


        s_SetGravNodeConnectionProperties.Begin();
        int startIndex = 0;

        for (int j = 0; j < gravNodes.Count; j++)
        {
            GravNode n = gravNodes[j];
            nodeNumConnections[j]    = n.m_Connections;
            startConnectionsIndex[j] = startIndex;
            for (int i = 0; i < n.m_Connections; i++)
            {
                allNodeConnections[i + startIndex] = n.neighborIndiciesList[i];
                allRestsDistances[i + startIndex]  = n.restDistancesList[i];
            }
            startIndex  += MAX_CONNECTIONS;
            moveables[j] = n.m_Moveable;
        }
        s_SetGravNodeConnectionProperties.End();
        s_ResetConnections.End();
    }
 public Link(GravNode gn1, GravNode gn2, bool draw, GravMesh gravMesh, float thickness, int index, float spacing)
 {
     m_Index = index;
     MakeLink(gn1, gn2, draw, gravMesh, thickness, spacing);
 }