コード例 #1
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            var barrier           = m_Barrier.CreateCommandBuffer().ToConcurrent();
            var level             = GetSingleton <LevelComponent>();
            var voxelBuffer       = m_Barrier.GetBufferFromEntity <VoxelBuffer>(false);
            var updateVoxelHandle = Entities
                                    .WithBurst()
                                    //.WithoutBurst()
                                    .WithNativeDisableParallelForRestriction(voxelBuffer)
                                    .WithName("Update_Chunk")
                                    .ForEach((Entity entity, int entityInQueryIndex, ref ChunkComponent cc, in UpdateChunkTag updateData, in LocalToParent pp) =>
            {
                barrier.RemoveComponent <UpdateChunkTag>(entityInQueryIndex, entity);
                var buffer  = voxelBuffer[entity];
                var stencil = updateData.input;

                var stencilCenter     = new float4(stencil.centerX, stencil.centerY, 0, 1);
                var translatedStencil = math.mul(math.inverse(pp.Value), stencilCenter);
                var xNeighbor         = cc.leftNeighbour;
                var yNeighbor         = cc.upNeighbour;

                stencil.centerX = translatedStencil.x;
                stencil.centerY = translatedStencil.y;

                {
                    int xStart = (int)(stencil.XStart / level.voxelSize);
                    int xEnd   = (int)((stencil.XEnd) / level.voxelSize);
                    int yStart = (int)(stencil.YStart / level.voxelSize);
                    int yEnd   = (int)(stencil.YEnd / level.voxelSize);

                    if (xStart < 0)
                    {
                        xStart = 0;
                    }
                    if (yStart < 0)
                    {
                        yStart = 0;
                    }
                    if (xEnd >= LevelComponent.VoxelResolution)
                    {
                        xEnd = LevelComponent.VoxelResolution - 1;
                    }
                    if (yEnd >= LevelComponent.VoxelResolution)
                    {
                        yEnd = LevelComponent.VoxelResolution - 1;
                    }

                    for (int y = yStart; y <= yEnd; y++)
                    {
                        for (int x = xStart; x <= xEnd; x++)
                        {
                            int i      = y * LevelComponent.VoxelResolution + x;
                            float2 pos = buffer[i].Value.position;
                            if (stencil.InRange(pos))
                            {
                                buffer[i] = buffer[i].Value.Copy(stencil.fillType);
                                if (stencil.shape == VoxelShape.Rectangle)
                                {
                                    handleSquareY(ref voxelBuffer, ref buffer, ref stencil, yNeighbor, x, y, i);
                                    handleSquareX(ref voxelBuffer, ref buffer, ref stencil, xNeighbor, x, y, i);
                                }
                                else
                                {
                                    handleCircleX(ref voxelBuffer, ref buffer, ref stencil, xNeighbor, x, y, i);
                                    handleCircleY(ref voxelBuffer, ref buffer, ref stencil, yNeighbor, x, y, i);
                                }
                            }
                        }
                    }
                }
                barrier.AddComponent <TriangulateTag>(entityInQueryIndex, entity);
            }).Schedule(inputDeps);
コード例 #2
0
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            inputDeps.Complete();
            var barrier = m_Barrier.CreateCommandBuffer().ToConcurrent();
            var bfe     = m_Barrier.GetBufferFromEntity <VoxelBuffer>(true);
            var level   = GetSingleton <LevelComponent>();
            var handle  = Entities
                          .WithBurst()
                          .WithReadOnly(bfe)
                          .WithName("Do_Triangulation")
                          .WithAll <RenderMesh>()
                          .ForEach((Entity entity, int entityInQueryIndex, ref ChunkComponent cc, in TriangulateTag updateData) =>
            {
                int edgeCacheMin = 0, edgeCacheMax = 0;

                var xNeighbour  = cc.leftNeighbour;
                var yNeighbour  = cc.upNeighbour;
                var xyNeighbour = cc.diagNeighbour;

                var rowCacheMax = new NativeArray <int>(LevelComponent.VoxelResolution * 2 + 1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                var rowCacheMin = new NativeArray <int>(LevelComponent.VoxelResolution * 2 + 1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

                barrier.RemoveComponent <TriangulateTag>(entityInQueryIndex, entity);

                var vertices  = barrier.AddBuffer <VectorBuffer>(entityInQueryIndex, entity);
                var triangles = barrier.AddBuffer <IntBuffer>(entityInQueryIndex, entity);


                FillFirstRowCache(level.chunkSize);
                TriangulateCellRows(level.chunkSize);
                if (cc.upNeighbour != Entity.Null)
                {
                    TriangulateGapRow(level.chunkSize);
                }
                rowCacheMax.Dispose();
                rowCacheMin.Dispose();

                barrier.AddComponent <MeshAssignTag>(entityInQueryIndex, entity);


                #region wtf tbh
                void FillFirstRowCache(float chunkSize)
                {
                    // first corner
                    var voxels = bfe[entity];
                    CacheFirstCorner(voxels[0]);
                    int i;
                    for (i = 0; i < LevelComponent.VoxelResolution - 1; i++)
                    {
                        CacheNextEdgeAndCorner(i * 2, voxels[i], voxels[i + 1]);
                    }
                    if (xNeighbour != Entity.Null)
                    {
                        var n = bfe[xNeighbour][0].Value.CopyDummyX(chunkSize);
                        CacheNextEdgeAndCorner(i * 2, voxels[i], n);
                    }
                }


                void CacheFirstCorner(Voxel voxel)
                {
                    if (voxel.state)
                    {
                        rowCacheMax[0] = vertices.Length;
                        vertices.Add(voxel.position);
                    }
                }

                void CacheNextEdgeAndCorner(int index, Voxel xMin, Voxel xMax)
                {
                    Debug.Assert(xMin.position.y == xMax.position.y);
                    if (xMin.state != xMax.state)
                    {
                        rowCacheMax[index + 1] = vertices.Length;
                        vertices.Add(xMin.XEdgePoint);
                    }
                    if (xMax.state)
                    {
                        rowCacheMax[index + 2] = vertices.Length;
                        vertices.Add(xMax.position);
                    }
                }

                void TriangulateCellRows(float chunkSize)
                {
                    var voxels = bfe[entity];
                    int cells  = LevelComponent.VoxelResolution - 1;
                    for (int i = 0, y = 0; y < cells; y++, i++)
                    {
                        SwapRowCaches();

                        CacheFirstCorner(voxels[i + LevelComponent.VoxelResolution]);
                        CacheNextMiddleEdge(voxels[i], voxels[i + LevelComponent.VoxelResolution]);
                        for (int x = 0; x < cells; x++, i++)
                        {
                            var a          = voxels[i];
                            var b          = voxels[i + 1];
                            var c          = voxels[i + LevelComponent.VoxelResolution];
                            var d          = voxels[i + LevelComponent.VoxelResolution + 1];
                            int cacheIndex = x * 2;
                            CacheNextEdgeAndCorner(cacheIndex, c, d);
                            CacheNextMiddleEdge(b, d);
                            TriangulateCell(cacheIndex, a, b, c, d);
                        }
                        if (xNeighbour != Entity.Null)
                        {
                            TriangulateGapCell(chunkSize, i);
                        }
                    }
                }



                void SwapRowCaches()
                {
                    var temp    = rowCacheMin;
                    rowCacheMin = rowCacheMax;
                    rowCacheMax = temp;
                }

                void CacheNextMiddleEdge(Voxel yMin, Voxel yMax)
                {
                    Debug.Assert(yMin.position.x == yMax.position.x);
                    Debug.Assert(yMin.position.y < yMax.position.y);
                    edgeCacheMin = edgeCacheMax;
                    if (yMin.state != yMax.state)
                    {
                        edgeCacheMax = vertices.Length;
                        vertices.Add(yMin.YEdgePoint);
                    }
                }

                void TriangulateGapCell(float chunkSize, int i)
                {
                    Debug.Assert(i % LevelComponent.VoxelResolution == (LevelComponent.VoxelResolution - 1));
                    var voxels     = bfe[entity];
                    int cacheIndex = (LevelComponent.VoxelResolution - 1) * 2;
                    var a          = voxels[i];
                    var b          = bfe[xNeighbour][i + 1 - LevelComponent.VoxelResolution].Value.CopyDummyX(chunkSize);
                    var c          = voxels[i + LevelComponent.VoxelResolution];
                    var d          = bfe[xNeighbour][i + 1].Value.CopyDummyX(chunkSize);

                    CacheNextEdgeAndCorner(cacheIndex, voxels[i + LevelComponent.VoxelResolution], d);
                    CacheNextMiddleEdge(b, d);
                    TriangulateCell(cacheIndex, a, b, c, d);
                }

                void TriangulateGapRow(float chunkSize)
                {
                    int cells  = LevelComponent.VoxelResolution - 1;
                    int offset = cells * LevelComponent.VoxelResolution;

                    var voxels          = bfe[entity];
                    var neighbourVoxels = bfe[yNeighbour];

                    var dummyY = neighbourVoxels[0].Value.CopyDummyY(chunkSize);

                    SwapRowCaches();
                    CacheFirstCorner(dummyY);
                    CacheNextMiddleEdge(voxels[cells * LevelComponent.VoxelResolution], dummyY);

                    for (int x = 0; x < cells; x++)
                    {
                        var dummyT     = dummyY.CopyDummyX(0);
                        dummyY         = neighbourVoxels[x + 1].Value.CopyDummyY(chunkSize);
                        var cacheIndex = x * 2;
                        CacheNextEdgeAndCorner(cacheIndex, dummyT, dummyY);
                        CacheNextMiddleEdge(voxels[x + offset + 1], dummyY);
                        TriangulateCell(cacheIndex, voxels[x + offset], voxels[x + offset + 1], dummyT, dummyY);
                    }

                    if (xyNeighbour != Entity.Null)
                    {
                        var leftVoxels = bfe[xNeighbour];
                        var a          = voxels[voxels.Length - 1];
                        var b          = leftVoxels[leftVoxels.Length - LevelComponent.VoxelResolution].Value.CopyDummyX(chunkSize);
                        var c          = neighbourVoxels[LevelComponent.VoxelResolution - 1].Value.CopyDummyY(chunkSize);
                        var d          = bfe[xyNeighbour][0].Value.CopyDummyXY(chunkSize);
                        Debug.Assert(a.Value.position.x == c.position.x);
                        Debug.Assert(a.Value.position.y == b.position.y);
                        Debug.Assert(b.position.x == d.position.x);
                        Debug.Assert(c.position.y == d.position.y);
                        var cacheIndex = cells * 2;
                        CacheNextEdgeAndCorner(cacheIndex, c, d);
                        CacheNextMiddleEdge(b, d);
                        TriangulateCell(cacheIndex, a, b, c, d);
                    }
                }

                void TriangulateCell(int i, in Voxel a, in Voxel b, in Voxel c, in Voxel d)
                {
                    var cas = 0;
                    if (a.state)
                    {
                        cas |= 0b0001;
                    }
                    if (b.state)
                    {
                        cas |= 0b0010;
                    }
                    if (c.state)
                    {
                        cas |= 0b0100;
                    }
                    if (d.state)
                    {
                        cas |= 0b1000;
                    }
                    switch (cas)
                    {
                    case 0:
                        break;

                    case 1:
                        AddTriangle(rowCacheMin[i], edgeCacheMin, rowCacheMin[i + 1], ref triangles);
                        break;

                    case 2:
                        AddTriangle(rowCacheMin[i + 2], rowCacheMin[i + 1], edgeCacheMax, ref triangles);
                        break;

                    case 3:
                        AddQuad(rowCacheMin[i], edgeCacheMin, edgeCacheMax, rowCacheMin[i + 2], ref triangles);
                        break;

                    case 4:
                        AddTriangle(rowCacheMax[i], rowCacheMax[i + 1], edgeCacheMin, ref triangles);
                        break;

                    case 5:
                        AddQuad(rowCacheMin[i], rowCacheMax[i], rowCacheMax[i + 1], rowCacheMin[i + 1], ref triangles);
                        break;

                    case 6:
                        AddTriangle(rowCacheMin[i + 2], rowCacheMin[i + 1], edgeCacheMax, ref triangles);
                        AddTriangle(rowCacheMax[i], rowCacheMax[i + 1], edgeCacheMin, ref triangles);
                        break;

                    case 7:
                        AddPentagon(
                            rowCacheMin[i], rowCacheMax[i], rowCacheMax[i + 1], edgeCacheMax, rowCacheMin[i + 2], ref triangles);
                        break;

                    case 8:
                        AddTriangle(rowCacheMax[i + 2], edgeCacheMax, rowCacheMax[i + 1], ref triangles);
                        break;

                    case 9:
                        AddTriangle(rowCacheMin[i], edgeCacheMin, rowCacheMin[i + 1], ref triangles);
                        AddTriangle(rowCacheMax[i + 2], edgeCacheMax, rowCacheMax[i + 1], ref triangles);
                        break;

                    case 10:
                        AddQuad(rowCacheMin[i + 1], rowCacheMax[i + 1], rowCacheMax[i + 2], rowCacheMin[i + 2], ref triangles);
                        break;

                    case 11:
                        AddPentagon(
                            rowCacheMin[i + 2], rowCacheMin[i], edgeCacheMin, rowCacheMax[i + 1], rowCacheMax[i + 2], ref triangles);
                        break;

                    case 12:
                        AddQuad(edgeCacheMin, rowCacheMax[i], rowCacheMax[i + 2], edgeCacheMax, ref triangles);
                        break;

                    case 13:
                        AddPentagon(
                            rowCacheMax[i], rowCacheMax[i + 2], edgeCacheMax, rowCacheMin[i + 1], rowCacheMin[i], ref triangles);
                        break;

                    case 14:
                        AddPentagon(
                            rowCacheMax[i + 2], rowCacheMin[i + 2], rowCacheMin[i + 1], edgeCacheMin, rowCacheMax[i], ref triangles);
                        break;

                    case 15:
                        AddQuad(rowCacheMin[i], rowCacheMax[i], rowCacheMax[i + 2], rowCacheMin[i + 2], ref triangles);
                        break;
                    }
                }

                #endregion
            }).Schedule(inputDeps);

            m_Barrier.AddJobHandleForProducer(handle);

            return(handle);
        }