Ejemplo n.º 1
0
        private LightJobData getJobData(Vector3Int chunkId)
        {
            NativeArray <bool> directionsValid = new NativeArray <bool>(DirectionExtensions.numDirections, Allocator.Persistent);

            for (int i = 0; i < DirectionExtensions.numDirections; i++)
            {
                var offset  = DirectionExtensions.Vectors[i];
                var neighId = chunkId + offset;
                //Chunk only valid (for propagation etc) if it's fully generated and not outside the world limits
                directionsValid[i] = chunkManager.IsChunkFullyGenerated(neighId) && !chunkManager.WorldLimits.ChunkOutsideVerticalLimits(neighId);
            }

            var chunkData = chunkManager.GetReadOnlyChunkData(chunkId);

            LightJobData jobData = new LightJobData(chunkId.ToNative(),
                                                    chunkManager.ChunkToWorldPosition(chunkId).ToInt().ToNative(),
                                                    chunkDimensions.ToNative(),
                                                    chunkData.ToNative(Allocator.Persistent),
                                                    chunkData.LightToNative(Allocator.Persistent),
                                                    JobUtils.CacheNeighbourData(chunkId, chunkManager),
                                                    directionsValid,
                                                    voxelTypeToEmissionMap,
                                                    voxelTypeToAbsorptionMap,
                                                    directionVectors
                                                    );

            return(jobData);
        }
        public AbstractPipelineJob <MeshDescriptor> CreateMeshJob(Vector3Int chunkID)
        {
            Profiler.BeginSample("CreateMeshJob");

            var chunkDimensions = chunkManager.ChunkDimensions;

            var chunkData = chunkManager.GetReadOnlyChunkData(chunkID);

            //Copy chunk data to native array
            Profiler.BeginSample("VoxelsToNative");
            NativeArray <VoxelTypeID> voxels = chunkData.ToNative();

            Profiler.EndSample();


            NeighbourData neighbourData = new NeighbourData();

            //Cache neighbour data
            neighbourData = JobUtils.CacheNeighbourData(chunkID, chunkManager);


            var meshingJob = createMeshingJob(new MeshJobData(chunkDimensions.ToNative(),
                                                              chunkManager.IncludeLighting,
                                                              voxels,
                                                              chunkData.NativeRotations(),
                                                              chunkData.LightToNative(),
                                                              neighbourData,
                                                              voxelTypeManager.nativeMeshDatabase,
                                                              voxelTypeManager.nativeVoxelTypeDatabase,
                                                              Allocator.Persistent
                                                              ));


            var indexingWrapper = new JobWrapper <SortIndicesByMaterialJob>();

            //AsDeferredJobArray takes the length etc at the time of execution, rather than now.
            indexingWrapper.job.allTriangleIndices             = meshingJob.data.allTriangleIndices.AsDeferredJobArray();
            indexingWrapper.job.materialRuns                   = meshingJob.data.materialRuns.AsDeferredJobArray();
            indexingWrapper.job.packedRuns                     = new NativeList <MaterialRun>(Allocator.Persistent);
            indexingWrapper.job.packedIndices                  = new NativeList <int>(Allocator.Persistent);
            indexingWrapper.job.collisionMeshMaterialRunLength = meshingJob.data.collisionSubmesh.collisionMeshMaterialRunLength;


            Func <MeshDescriptor> cleanup = () =>
            {
                Profiler.BeginSample("MeshJobCleanup");
                Mesh mesh = new Mesh();

                if (meshingJob.data.vertices.Length >= ushort.MaxValue)
                {
                    //Cope with bigger meshes
                    mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                }

                mesh.vertices = meshingJob.data.vertices.ToArray();
                if (meshingJob.data.includeLighting)
                {
                    mesh.colors = meshingJob.data.vertexColours.ToArray();
                }
                mesh.SetUVs(0, meshingJob.data.uvs.ToArray());
                mesh.normals = meshingJob.data.normals.ToArray();

                mesh.subMeshCount = indexingWrapper.job.packedRuns.Length;

                MeshDescriptor meshDescriptor = new MeshDescriptor();
                meshDescriptor.materialsBySubmesh = new Material[mesh.subMeshCount];

                for (int i = 0; i < indexingWrapper.job.packedRuns.Length; i++)
                {
                    var run   = indexingWrapper.job.packedRuns[i];
                    var slice = new NativeSlice <int>(indexingWrapper.job.packedIndices, run.range.start, run.range.Length);
                    mesh.SetTriangles(slice.ToArray(), i);
                    meshDescriptor.materialsBySubmesh[i] = voxelTypeManager.GetMaterial(run.materialID);
                }

                meshDescriptor.mesh = mesh;
                meshDescriptor.collidableLengthVertices = meshingJob.data.collisionSubmesh.collisionMeshLengthVertices[0];
                meshDescriptor.collidableLengthIndices  = meshingJob.data.collisionSubmesh.collisionMeshLengthTriangleIndices[0];

                //Disposal
                meshingJob.Dispose();

                //Dispose of packed containers
                indexingWrapper.job.packedIndices.Dispose();
                indexingWrapper.job.packedRuns.Dispose();

                Profiler.EndSample();

                return(meshDescriptor);
            };

            Profiler.EndSample();


            //Single threaded version
            if (!Parrallel)
            {
                return(new BasicFunctionJob <MeshDescriptor>(() =>
                {
                    meshingJob.Run();
                    indexingWrapper.Run();
                    return cleanup();
                }));
            }

            var meshingHandle = meshingJob.Schedule();
            var handle        = indexingWrapper.Schedule(meshingHandle);

            return(new PipelineUnityJob <MeshDescriptor>(handle, cleanup));
        }