예제 #1
0
 private void LoadChunk(VoxelWorld _voxel_world, intVector3 _position)
 {
     if (_voxel_world.GetChunk(_position.x, _position.y, _position.z) == null)
     {
         _voxel_world.CreateChunk(_position.x, _position.y, _position.z);
     }
 }
예제 #2
0
    public void ReuseChunk(Chunk _chunk, intVector3 _position)
    {
        // intVector3 voxel_world_position = new intVector3(_x, _y, _z);//the coordinates of chunk in the world

        if (_chunk == null)
        {
            CreateChunk(_position.x, _position.y, _position.z);
        }

        _chunk.transform.position   = _position;
        _chunk.voxel_world_position = _position;

        _chunk.gameObject.SetActive(true);

        _chunk.voxel_world         = this;
        _chunk.transform.parent    = transform;
        _chunk.name                = "World Chunk";
        _chunk.gameObject.isStatic = true;

        chunks.Add(_position, _chunk);//store chunk in dictionary by its position
        _chunk = terrain_generator.GenerateChunk(_chunk);

        _chunk.SetVoxelsUnEdited();
        VoxelWorldSaver.Load(_chunk);
    }
예제 #3
0
    public void CreateChunk(int _x, int _y, int _z)
    {
        intVector3 voxel_world_position = new intVector3(_x, _y, _z);//the coordinates of chunk in the world

        if (chunks.ContainsKey(voxel_world_position))
        {
            return;
        }

        GameObject chunk_object = Instantiate(chunk_prefab, new Vector3(voxel_world_position.x,
                                                                        voxel_world_position.y, voxel_world_position.z), Quaternion.Euler(Vector3.zero));//create chunk

        //set chunk parameters
        Chunk chunk = chunk_object.GetComponent <Chunk>();

        chunk.voxel_world_position = voxel_world_position;
        chunk.voxel_world          = this;
        chunk.transform.parent     = transform;
        chunk.name = "World Chunk";
        chunk.gameObject.isStatic = true;

        chunks.Add(voxel_world_position, chunk);//store chunk in dictionary by its position
        chunk = terrain_generator.GenerateChunk(chunk);

        chunk.SetVoxelsUnEdited();
        VoxelWorldSaver.Load(chunk);
    }
예제 #4
0
    public Chunk GetChunkUnFloored(intVector3 _position)
    {
        Chunk chunk = null;

        chunks.TryGetValue(_position, out chunk);

        return(chunk);
    }
        public void SetBoundary(Vector3 _size, ComputeBuffer _obstacle_grid, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            int kernel_id = compute_shader.FindKernel("Boundary");

            compute_shader.SetBuffer(kernel_id, "write_R", _obstacle_grid);
            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
        }
예제 #6
0
    private void ReuseChunk(VoxelWorld _voxel_world, intVector3 _position)
    {
        if (_voxel_world.GetChunk(_position.x, _position.y, _position.z) != null)
        {
            return;
        }

        _voxel_world.ReuseChunk(GetChunkFromPool(), _position);//reuse chunk if available
    }
예제 #7
0
    public override bool Equals(object _object)// Override equals operator
    {
        if (!(_object is intVector3))
        {
            return(false);// Ignore
        }
        intVector3 position = (intVector3)_object;

        return(position.x == x && position.y == y && position.z == z);
    }
    public override bool Equals(object _object)    //override equals operator
    {
        if (!(_object is intVector3))              //if not a world position
        {
            return(false);                         //ignore
        }
        intVector3 position = (intVector3)_object; //cast to world position

        return(position.x == x && position.y == y && position.z == z);
    }
        private intVector3 CustomOutputThreadCount()
        {
            intVector3 custom_thread_count = intVector3.Zero;

            custom_thread_count.x = (int)(output_resolution.x / THREAD_GROUP_COUNT); // Compute shaders use thread groups
            custom_thread_count.y = (int)(output_resolution.y / THREAD_GROUP_COUNT); // Divide by the amount of groups to get required thread count for grid size
            custom_thread_count.z = (int)(output_resolution.z / THREAD_GROUP_COUNT);

            return(custom_thread_count);
        }
예제 #10
0
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        foreach (intVector3 chunk_pos in chunk_positions)
        {
            intVector3 chunk_relative_pos = new intVector3(chunk_pos.x * Chunk.chunk_size + current_world_position.x, current_world_position.y,
                                                           chunk_pos.z * Chunk.chunk_size + current_world_position.z);

            Gizmos.DrawWireCube(chunk_relative_pos, Vector3.one * Chunk.chunk_size);
        }
    }
예제 #11
0
    private void Update()
    {
        current_world_position = VoxelWorld.PositionToWorldPosition(transform.position);

        if (multithreading)
        {
            ThreadedUpdate();
            return;
        }

        RegularUpdate();
    }
        protected override RenderTexture ConvertGridToVolume(GridType _grid_type)
        {
            if (_grid_type != GridType.DENSITY)
            {
                return(base.ConvertGridToVolume(_grid_type)); // Let base handle other output conversions
            }
            intVector3 custom_thread_count = CustomOutputThreadCount();

            output_module.FuelParticleToVolume(output_resolution, fuel_particles_buffer,
                                               custom_volume_output, particle_count, explosion_params.trace_particles, custom_thread_count);

            return(custom_volume_output);
        }
예제 #13
0
    public static bool SetVoxel(RaycastHit _hit, Voxel _voxel, bool _adjacent = false)
    {
        Chunk chunk = _hit.collider.GetComponent <Chunk>();//try get chunk

        if (chunk == null)
        {
            return(false);//failed to get chunk
        }
        intVector3 position = GetVoxelCentrePosition(_hit, _adjacent);

        chunk.voxel_world.SetVoxel(position.x, position.y, position.z, _voxel);

        return(true);
    }
예제 #14
0
    public static Voxel GetVoxel(RaycastHit _hit, bool _adjacent = false)
    {
        Chunk chunk = _hit.collider.GetComponent <Chunk>();

        if (chunk == null)
        {
            return(null);
        }

        intVector3 position = GetVoxelCentrePosition(_hit, _adjacent);
        Voxel      voxel    = chunk.voxel_world.GetVoxel(position.x, position.y, position.z);

        return(voxel);
    }
예제 #15
0
    void SetNeighbourEditedIfEqual(int _voxel_chunk_position, int _check_value, intVector3 _position)
    {
        if (_voxel_chunk_position != _check_value)
        {
            return;
        }

        Chunk chunk = GetChunk(_position.x, _position.y, _position.z);

        if (chunk != null)
        {
            chunk.edited = true;//set chunk as edited so it updates
        }
    }
예제 #16
0
    public Chunk GetChunk(int _x, int _y, int _z)
    {
        intVector3 position   = new intVector3();
        float      chunk_size = Chunk.chunk_size;//convert to float for division

        position.x = Mathf.FloorToInt(_x / chunk_size) * Chunk.chunk_size;
        position.y = Mathf.FloorToInt(_y / chunk_size) * Chunk.chunk_size;
        position.z = Mathf.FloorToInt(_z / chunk_size) * Chunk.chunk_size;

        Chunk chunk = null;

        chunks.TryGetValue(position, out chunk);

        return(chunk);
    }
예제 #17
0
        public void ApplyImpulse(float _dt, Vector3 _size, float _amount, float _impulse_radius,
                                 Vector3 _impulse_position, ComputeBuffer[] _grids, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            compute_shader.SetFloat("radius", _impulse_radius);
            compute_shader.SetFloat("source_amount", _amount);
            compute_shader.SetFloat("dt", _dt);
            compute_shader.SetVector("source_pos", _impulse_position);

            int kernel_id = compute_shader.FindKernel("Impulse");

            compute_shader.SetBuffer(kernel_id, "read_R", _grids[READ]);
            compute_shader.SetBuffer(kernel_id, "write_R", _grids[WRITE]);
            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
            Swap(_grids);
        }
예제 #18
0
    private void AddChunkPositionsToLoadLists(intVector3 _chunk_pos)
    {
        int column_height = Mathf.FloorToInt(max_chunk_y * 0.5f);

        for (int y = -column_height; y < column_height; ++y)                                                           //load a column of chunks in this position
        {
            for (int x = _chunk_pos.x - Chunk.chunk_size; x <= _chunk_pos.x + Chunk.chunk_size; x += Chunk.chunk_size) //add adjacent chunks as well so they get updated
            {
                for (int z = _chunk_pos.z - Chunk.chunk_size; z <= _chunk_pos.z + Chunk.chunk_size; z += Chunk.chunk_size)
                {
                    load_list.Add(new intVector3(x, y * Chunk.chunk_size, z));
                }
            }
            update_list.Add(new intVector3(_chunk_pos.x, y * Chunk.chunk_size, _chunk_pos.z));
        }
    }
예제 #19
0
        public void CalculatePressure(Vector3 _size, ComputeBuffer _divergence_grid,
                                      ComputeBuffer _obstacle_grid, uint _jacobi_iterations,
                                      ComputeBuffer[] _pressure_grids, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            int kernel_id = compute_shader.FindKernel("Jacobi");

            compute_shader.SetBuffer(kernel_id, "divergence", _divergence_grid);
            compute_shader.SetBuffer(kernel_id, "obstacles", _obstacle_grid);

            for (int i = 0; i < _jacobi_iterations; ++i)// Pressure gradient is calculated iteratively, most expensive part
            {
                compute_shader.SetBuffer(kernel_id, "write_R", _pressure_grids[WRITE]);
                compute_shader.SetBuffer(kernel_id, "pressure", _pressure_grids[READ]);
                compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
                Swap(_pressure_grids);
            }
        }
예제 #20
0
    void LoadAndUpdateThreadSafe()
    {
        if (load_list.Count != 0)
        {
            for (int i = 0; i < load_list.Count; ++i)
            {
                intVector3 temp = load_list[0];
                thread_manager.QueueForMainThread(() =>
                {
                    if (object_pooling)
                    {
                        ReuseChunk(voxel_world, temp);
                    }
                    else
                    {
                        LoadChunk(voxel_world, temp);
                    }
                });

                load_list.RemoveAt(0);//index 0 as entries are removed
            }
        }

        if (update_list.Count == 0)
        {
            return;
        }

        for (int i = 0; i < update_list.Count; ++i)
        {
            intVector3 temp = update_list[0];
            thread_manager.QueueForMainThread(() =>
            {
                Chunk chunk = voxel_world.GetChunk(temp.x, temp.y, temp.z);//try and get chunk

                if (chunk != null)
                {
                    chunk.edited = true;//set it to update its mesh
                }
            });

            update_list.RemoveAt(0);
        }
    }
예제 #21
0
    public void SetVoxel(int _x, int _y, int _z, Voxel _voxel)
    {
        Chunk chunk = GetChunk(_x, _y, _z);

        if (chunk == null)
        {
            return;
        }

        intVector3 voxel_chunk_pos = new intVector3(_x - chunk.voxel_world_position.x,
                                                    _y - chunk.voxel_world_position.y, _z - chunk.voxel_world_position.z);

        chunk.SetVoxel(voxel_chunk_pos.x, voxel_chunk_pos.y, voxel_chunk_pos.z, _voxel);
        chunk.edited = true;

        //update neighbouring chunks
        SetNeighbourEditedIfEqual(voxel_chunk_pos.x, 0, new intVector3(_x - 1, _y, _z));//if offset x - 1 less than zero (in adjacent chunk) the neighbouring chunk should update
        SetNeighbourEditedIfEqual(voxel_chunk_pos.x, Chunk.chunk_size - 1, new intVector3(_x + 1, _y, _z));
        SetNeighbourEditedIfEqual(voxel_chunk_pos.y, 0, new intVector3(_x, _y - 1, _z));
        SetNeighbourEditedIfEqual(voxel_chunk_pos.y, Chunk.chunk_size - 1, new intVector3(_x, _y + 1, _z));
        SetNeighbourEditedIfEqual(voxel_chunk_pos.z, 0, new intVector3(_x, _y, _z - 1));
        SetNeighbourEditedIfEqual(voxel_chunk_pos.z, Chunk.chunk_size - 1, new intVector3(_x, _y, _z + 1));
    }
예제 #22
0
    private void FindChunksToLoad()
    {
        if (update_list.Count != 0)//if there are chunks to build don't load more
        {
            return;
        }

        for (int i = 0; i < chunk_positions.Count; ++i)//for every pre calculated chunk position
        {
            //calculate chunk position
            intVector3 chunk_pos = new intVector3(chunk_positions[i].x * Chunk.chunk_size + current_world_position.x, 0,
                                                  chunk_positions[i].z * Chunk.chunk_size + current_world_position.z); //offset array pos to players pos then convert to chunk pos

            Chunk chunk = voxel_world.GetChunk(chunk_pos.x, chunk_pos.y, chunk_pos.z);                                 //try find chunk at position
            if (ChunkScheduled(chunk, chunk_pos))                                                                      //if chunk is already loaded or scheduled to build, skip it
            {
                continue;
            }

            AddChunkPositionsToLoadLists(chunk_pos);

            return;
        }
    }
예제 #23
0
        public void ConvertToVolume(Vector3 _size, ComputeBuffer _grid, RenderTexture _target, intVector3 _thread_count)
        {
            // Convert structured buffer to 3d volume texture using gpu
            int kernel_id = compute_shader.FindKernel("ConvertToVolume");

            compute_shader.SetBuffer(kernel_id, "read_R", _grid);
            compute_shader.SetTexture(kernel_id, "write_tex", _target);
            compute_shader.SetVector("size", _size);
            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
        }
예제 #24
0
        public void FuelParticleToVolume(Vector3 _size, ComputeBuffer _particles, RenderTexture _target, uint _particle_count, bool _trace_particles, intVector3 _thread_count)
        {
            // Convert particles buffer to 3d volume texture using gpu
            int kernel_id = compute_shader.FindKernel("ParticleToVolume");

            compute_shader.SetBuffer(kernel_id, "particles", _particles);
            compute_shader.SetTexture(kernel_id, "write_tex", _target);
            compute_shader.SetVector("size", _size);

            if (!_trace_particles)                                           // If not tracing particles I have to clear the volume each frame
            {
                int clear_kernel = compute_shader.FindKernel("ClearVolume"); // GL.Clear doesn't seem to work for 3D RenderTexture
                compute_shader.SetTexture(clear_kernel, "write_tex", _target);
                compute_shader.Dispatch(clear_kernel, _thread_count.x, _thread_count.y, _thread_count.z);
            }

            compute_shader.Dispatch(kernel_id, (int)_particle_count / 8, 1, 1);
        }
예제 #25
0
 private bool ChunkScheduled(Chunk _chunk, intVector3 _chunk_pos)
 {
     return(_chunk != null && (_chunk.rendered || update_list.Contains(_chunk_pos)));
 }
예제 #26
0
        public void CalculateProjection(Vector3 _size, ComputeBuffer[] _pressure_grids,
                                        ComputeBuffer _obstacle_grid, ComputeBuffer[] _velocity_grids, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            int kernel_id = compute_shader.FindKernel("Projection");

            compute_shader.SetBuffer(kernel_id, "obstacles", _obstacle_grid);
            compute_shader.SetBuffer(kernel_id, "pressure", _pressure_grids[READ]);
            compute_shader.SetBuffer(kernel_id, "velocity", _velocity_grids[READ]);
            compute_shader.SetBuffer(kernel_id, "write_RGB", _velocity_grids[WRITE]);

            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
            Swap(_velocity_grids);
        }
예제 #27
0
        public void ApplyBuoyancy(float _dt, Vector3 _size, float _buoyancy, float _particle_weight, float _ambient_temperature,
                                  ComputeBuffer[] _velocity_grids, ComputeBuffer[] _density_grids, ComputeBuffer[] _temperature_grids, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            compute_shader.SetVector("up", new Vector4(0, 1, 0, 0));// Up is up, normally
            compute_shader.SetFloat("buoyancy", _buoyancy);
            compute_shader.SetFloat("weight", _particle_weight);
            compute_shader.SetFloat("ambient_temperature", _ambient_temperature);
            compute_shader.SetFloat("dt", _dt);

            int kernel_id = compute_shader.FindKernel("ApplyBuoyancy");

            compute_shader.SetBuffer(kernel_id, "write_RGB", _velocity_grids[WRITE]);
            compute_shader.SetBuffer(kernel_id, "velocity", _velocity_grids[READ]);
            compute_shader.SetBuffer(kernel_id, "density", _density_grids[READ]);
            compute_shader.SetBuffer(kernel_id, "temperature", _temperature_grids[READ]);

            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
            Swap(_velocity_grids);
        }
 public static string GetChunkFileName(intVector3 _chunk_position)
 {
     return(_chunk_position.x + "," + _chunk_position.y + "," + _chunk_position.z + ".bin");
 }
        public void CalculateDivergence(Vector3 _size, ComputeBuffer _divergence_grid,
                                        ComputeBuffer[] _velocity_grids, ComputeBuffer _obstacle_grid, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);
            int kernel_id = compute_shader.FindKernel("Divergence");

            compute_shader.SetBuffer(kernel_id, "write_R", _divergence_grid);
            compute_shader.SetBuffer(kernel_id, "velocity", _velocity_grids[READ]);
            compute_shader.SetBuffer(kernel_id, "obstacles", _obstacle_grid);
            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
        }
        public void AddSphereObstacle(Vector3 _size, Vector3 _position, float _radius, bool _is_container, ComputeBuffer _obstacle_grid, intVector3 _thread_count)
        {
            compute_shader.SetVector("size", _size);

            int kernel_id = _is_container ? compute_shader.FindKernel("AddSphereContainer") :
                            compute_shader.FindKernel("AddSphereObstacle");// Separate function for container to avoid branching on GPU

            compute_shader.SetBuffer(kernel_id, "write_R", _obstacle_grid);
            compute_shader.SetFloat("sphere_radius", _radius);
            compute_shader.SetVector("sphere_position", _position);
            compute_shader.Dispatch(kernel_id, _thread_count.x, _thread_count.y, _thread_count.z);
        }