예제 #1
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 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);
        }