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); }