public void Execute()
        {
            var width  = source.Length(0);
            var height = source.Length(1);
            var depth  = source.Length(2);

            for (int z = 0; z < chunkSize; z++)
            {
                for (int y = 0; y < chunkSize; y++)
                {
                    for (int x = 0; x < chunkSize; x++)
                    {
                        var cvx = x + tx;
                        var cvy = y + ty;
                        var cvz = z + tz;

                        var gvx = x + gx;
                        var gvy = y + gy;
                        var gvz = z + gz;

                        if (cvx >= 0 && cvx < chunkSize && cvy >= 0 && cvy < chunkSize && cvz >= 0 && cvz < chunkSize &&
                            gvx >= 0 && gvx < width && gvy >= 0 && gvy < height && gvz >= 0 && gvz < depth)
                        {
                            Voxel sourceVoxel = source[gvx, gvy, gvz];
                            if (writeUnsetVoxels || sourceVoxel.Data.IsVoxelSet)
                            {
                                target[cvx, cvy, cvz] = sourceVoxel;
                            }
                        }
                    }
                }
            }
        }
Example #2
0
        public void Execute()
        {
            int nVoxels = Voxels.Length(0) * Voxels.Length(1) * Voxels.Length(2);
            int nCells  = (Voxels.Length(0) - 1) * (Voxels.Length(1) - 1) * (Voxels.Length(2) - 1);

            var MemoryCache = new NativeMemoryCache(Allocator.Temp);
            var DedupeCache = new VoxelMeshTessellation.NativeDeduplicationCache(Allocator.Temp);

            var Components = new NativeList <VoxelMeshComponent>(Allocator.Temp);
            var Indices    = new NativeList <PackedIndex>(Allocator.Temp);
            var Vertices   = new NativeList <VoxelMeshComponentVertex>(Allocator.Temp);

            var Materials     = new NativeArray <int>(8, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var Intersections = new NativeArray <float>(12, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var Normals       = new NativeArray <float3>(12, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

            var solver = new SvdQefSolver <RawArrayVoxelCell>
            {
                Clamp = false
            };
            var polygonizer = new CMSVoxelPolygonizer <RawArrayVoxelCell, CMSProperties.DataStruct, SvdQefSolver <RawArrayVoxelCell>, IntersectionSharpFeatureSolver <RawArrayVoxelCell> >(PolygonizationProperties, solver, new IntersectionSharpFeatureSolver <RawArrayVoxelCell>(), MemoryCache);

            int xSize = Voxels.Length(0);
            int ySize = Voxels.Length(1);
            int zSize = Voxels.Length(2);

            TIndexer indexer = Voxels.Indexer;

            for (int index = 0; index < nVoxels; ++index)
            {
                int x = 0, y = 0, z = 0;
                indexer.FromIndex(index, ref x, ref y, ref z);

                if (x < xSize - 1 && y < ySize - 1 && z < zSize - 1 && FillCell(Voxels, x, y, z, 0, Materials, Intersections, Normals))
                {
                    //TODO Directly operate on voxel array
                    RawArrayVoxelCell cell = new RawArrayVoxelCell(0, new float3(x, y, z), Materials, Intersections, Normals);

                    polygonizer.Polygonize(cell, Components, Indices, Vertices);
                }
            }

            VoxelMeshTessellation.Tessellate(Components, Indices, Vertices, Matrix4x4.identity, MeshVertices, MeshTriangles, MeshNormals, MeshMaterials, new MaterialColors(), MeshColors, DedupeCache);

            MemoryCache.Dispose();
            DedupeCache.Dispose();

            Materials.Dispose();
            Intersections.Dispose();
            Normals.Dispose();

            Components.Dispose();
            Indices.Dispose();
            Vertices.Dispose();

            //Cells.Dispose();
        }
Example #3
0
        public Change ScheduleSdf <TSdf>(float ox, float oy, float oz, TSdf sdf, int material, bool replace)
            where TSdf : struct, ISdf
        {
            var changed   = new NativeArray <bool>(1, Allocator.TempJob);
            var outVoxels = new NativeArray3D <Voxel, TIndexer>(indexerFactory(voxels.Length(0), voxels.Length(1), voxels.Length(2)), voxels.Length(0), voxels.Length(1), voxels.Length(2), Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

            var sdfJob = new ChunkSdfJob <TSdf, TIndexer>
            {
                origin    = new float3(ox, oy, oz),
                sdf       = sdf,
                material  = material,
                replace   = replace,
                snapshot  = voxels,
                changed   = changed,
                outVoxels = outVoxels
            };

            return(new Change(sdfJob.Schedule(), () =>
            {
                voxels.Dispose();
                voxels = outVoxels;

                if (sdfJob.changed[0])
                {
                    NeedsRebuild = true;
                }
                changed.Dispose();

                //Update the padding of all -X/-Y/-Z adjacent chunks
                //TODO Only propagate those sides that have changed
                PropagatePadding();
            }
                              ));
        }
        public void ApplyGrid <TGridIndexer>(int x, int y, int z, NativeArray3D <Voxel, TGridIndexer> grid, bool propagatePadding, bool includePadding, VoxelEditConsumer <TIndexer> edits, bool writeToChunks = true, bool writeUnsetVoxels = false)
            where TGridIndexer : struct, IIndexer
        {
            int minX = Mathf.FloorToInt((float)x / ChunkSize);
            int minY = Mathf.FloorToInt((float)y / ChunkSize);
            int minZ = Mathf.FloorToInt((float)z / ChunkSize);

            int maxX = Mathf.FloorToInt((float)(x + grid.Length(0)) / ChunkSize);
            int maxY = Mathf.FloorToInt((float)(y + grid.Length(1)) / ChunkSize);
            int maxZ = Mathf.FloorToInt((float)(z + grid.Length(2)) / ChunkSize);

            var handles = new List <VoxelChunk <TIndexer> .FinalizeChange>();

            var watch = System.Diagnostics.Stopwatch.StartNew();

            if (edits != null)
            {
                var snapshots = new List <VoxelChunk <TIndexer> .Snapshot>();

                //Include padding
                int minX2 = Mathf.FloorToInt((float)(x - 1) / ChunkSize);
                int minY2 = Mathf.FloorToInt((float)(y - 1) / ChunkSize);
                int minZ2 = Mathf.FloorToInt((float)(z - 1) / ChunkSize);

                int maxX2 = Mathf.FloorToInt((float)(x + grid.Length(0) + 1) / ChunkSize);
                int maxY2 = Mathf.FloorToInt((float)(y + grid.Length(1) + 1) / ChunkSize);
                int maxZ2 = Mathf.FloorToInt((float)(z + grid.Length(2) + 1) / ChunkSize);

                var snapshotChunks = new List <VoxelChunk <TIndexer> >();

                for (int cx = minX2; cx <= maxX2; cx++)
                {
                    for (int cy = minY2; cy <= maxY2; cy++)
                    {
                        for (int cz = minZ2; cz <= maxZ2; cz++)
                        {
                            ChunkPos chunkPos = ChunkPos.FromChunk(cx, cy, cz);

                            chunks.TryGetValue(chunkPos, out VoxelChunk <TIndexer> chunk);
                            if (chunk != null)
                            {
                                snapshots.Add(chunk.ScheduleSnapshot());
                            }
                            else
                            {
                                snapshotChunks.Add(new VoxelChunk <TIndexer>(this, chunkPos, ChunkSize, IndexerFactory));
                            }
                        }
                    }
                }

                //Finalize clone jobs
                foreach (VoxelChunk <TIndexer> .Snapshot snapshot in snapshots)
                {
                    snapshot.handle.Complete();
                    snapshotChunks.Add(snapshot.chunk);
                }

                //Produce edit
                edits(new VoxelEdit <TIndexer>(this, snapshotChunks));
            }

            if (writeToChunks)
            {
                var changes = new List <VoxelChunk <TIndexer> .Change>();

                //Schedule all jobs
                for (int cx = minX; cx <= maxX; cx++)
                {
                    for (int cy = minY; cy <= maxY; cy++)
                    {
                        for (int cz = minZ; cz <= maxZ; cz++)
                        {
                            ChunkPos chunkPos = ChunkPos.FromChunk(cx, cy, cz);

                            chunks.TryGetValue(chunkPos, out VoxelChunk <TIndexer> chunk);
                            if (chunk == null)
                            {
                                chunks[chunkPos] = chunk = new VoxelChunk <TIndexer>(this, chunkPos, ChunkSize, IndexerFactory);
                            }

                            var gx = (cx - minX) * ChunkSize;
                            var gy = (cy - minY) * ChunkSize;
                            var gz = (cz - minZ) * ChunkSize;

                            changes.Add(chunk.ScheduleGrid(0, 0, 0, gx, gy, gz, grid, propagatePadding, includePadding, writeUnsetVoxels));
                        }
                    }
                }

                //Wait and finalize jobs
                foreach (var change in changes)
                {
                    change.handle.Complete();
                }

                //Finalize
                foreach (var change in changes)
                {
                    change.finalize();
                }
            }
        }
        public static bool ApplySdf(NativeArray3D <Voxel, TIndexer> snapshot, float3 origin, TSdf sdf, int material, bool replace, NativeArray3D <Voxel, TIndexer> outVoxels, Allocator allocator)
        {
            int chunkSize = snapshot.Length(0) - 1;

            float3 minBound = math.floor(origin + sdf.Min());
            float3 maxBound = math.ceil(origin + sdf.Max());

            snapshot.CopyTo(outVoxels);

            var evaluatedSdf = new NativeArray3D <float, LinearIndexer>(new LinearIndexer(chunkSize + 1, chunkSize + 1, chunkSize + 1), chunkSize + 1, chunkSize + 1, chunkSize + 1, allocator);

            bool changed = false;

            //Apply materials
            for (int z = (int)minBound.z; z <= maxBound.z + 1; z++)
            {
                for (int y = (int)minBound.y; y <= maxBound.y + 1; y++)
                {
                    for (int x = (int)minBound.x; x <= maxBound.x + 1; x++)
                    {
                        if (x >= 0 && x < chunkSize + 1 && y >= 0 && y < chunkSize + 1 && z >= 0 && z < chunkSize + 1)
                        {
                            bool isInside = (evaluatedSdf[x, y, z] = sdf.Eval(new float3(x, y, z) - origin)) < 0;

                            if (isInside)
                            {
                                if (replace && outVoxels[x, y, z].Material != 0)
                                {
                                    //TODO Does this need intersection value checks?
                                    outVoxels[x, y, z] = outVoxels[x, y, z].ModifyMaterial(true, material);
                                    changed            = true;
                                }
                                else if (!replace && outVoxels[x, y, z].Material != material)
                                {
                                    outVoxels[x, y, z] = outVoxels[x, y, z].ModifyMaterial(true, material);
                                    changed            = true;
                                }
                            }
                        }
                    }
                }
            }

            //Apply intersections and normals in a second pass, such that they aren't unnecessarily
            //asigned to edges with no material change
            for (int z = (int)minBound.z; z <= maxBound.z; z++)
            {
                for (int y = (int)minBound.y; y <= maxBound.y; y++)
                {
                    for (int x = (int)minBound.x; x <= maxBound.x; x++)
                    {
                        if (x >= 0 && x < chunkSize && y >= 0 && y < chunkSize && z >= 0 && z < chunkSize)
                        {
                            ApplySdfIntersection(snapshot, origin, x, y, z, chunkSize, 0, 1, 0, 0, sdf, evaluatedSdf, material, replace, outVoxels);
                            ApplySdfIntersection(snapshot, origin, x, y, z, chunkSize, 1, 0, 1, 0, sdf, evaluatedSdf, material, replace, outVoxels);
                            ApplySdfIntersection(snapshot, origin, x, y, z, chunkSize, 2, 0, 0, 1, sdf, evaluatedSdf, material, replace, outVoxels);
                        }
                    }
                }
            }

            evaluatedSdf.Dispose();

            return(changed);
        }