168 lines
3.8 KiB
C#
168 lines
3.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
struct DifferentialEquationData
|
|
{
|
|
public float water;
|
|
public float vegetation;
|
|
}
|
|
public class GrassController : MonoBehaviour
|
|
{
|
|
int _structSize()
|
|
{
|
|
return sizeof(float) + sizeof(float);
|
|
}
|
|
private GameObject cube;
|
|
|
|
public float updateInterval;
|
|
float timePassed;
|
|
Terrain terrain;
|
|
public ComputeShader computeShader;
|
|
|
|
[Header("equation coeffs")]
|
|
public float DWater = 1.0f;
|
|
public float DVegetation = 0.5f;
|
|
public float feedRate = 0.055f;
|
|
public float killRate = 0.0462f;
|
|
public float dT = 0.10f;
|
|
public int stepsNumber = 1;
|
|
|
|
|
|
int sizeX;
|
|
int sizeY;
|
|
|
|
ComputeBuffer vegetation;
|
|
ComputeBuffer oldVegetation;
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
terrain = gameObject.GetComponent<Terrain>();
|
|
|
|
sizeX = terrain.terrainData.detailWidth;
|
|
sizeY = terrain.terrainData.detailHeight;
|
|
|
|
initComputeShader();
|
|
}
|
|
|
|
|
|
bool doUpdate()
|
|
{
|
|
timePassed += Time.deltaTime;
|
|
if (timePassed < updateInterval)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
timePassed = 0;
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
void initKillFeedBuffers()
|
|
{
|
|
//tutaj stworz
|
|
}
|
|
public void initBufferValues()
|
|
{
|
|
|
|
// tutaj uzupelnij wartosci buforow
|
|
float[] initValues = new float[sizeX * sizeY];
|
|
|
|
for (int i = 0; i < sizeX * sizeY; i++)
|
|
{
|
|
initValues[i] = Random.Range(0.0f, 1.0f);
|
|
}
|
|
vegetation.SetData(initValues);
|
|
oldVegetation.SetData(initValues);
|
|
}
|
|
|
|
public void resetGrass()
|
|
{
|
|
initBufferValues();
|
|
|
|
//var detail = new int[sizeX, sizeY];
|
|
|
|
//for (int i = 0; i < sizeX; i++) {
|
|
// detail[i, i] = 16;
|
|
//}
|
|
//terrain.terrainData.SetDetailLayer(0, 0, 1, detail);
|
|
|
|
|
|
|
|
|
|
}
|
|
void initParameters()
|
|
{
|
|
//tutaj zainicjalizuj parametry
|
|
computeShader.SetInt("sizeX", sizeX);
|
|
computeShader.SetInt("sizeY", sizeY);
|
|
|
|
}
|
|
void initComputeShader()
|
|
{
|
|
//tutaj zainicjalizuj compute shader
|
|
vegetation = new ComputeBuffer(sizeX * sizeY, sizeof(float));
|
|
oldVegetation = new ComputeBuffer(sizeX * sizeY, sizeof(float));
|
|
|
|
computeShader.SetBuffer(0, "vegetation", vegetation);
|
|
computeShader.SetBuffer(0, "oldVegetation", oldVegetation);
|
|
|
|
initKillFeedBuffers();
|
|
initBufferValues();
|
|
initParameters();
|
|
}
|
|
|
|
|
|
void swapBuffers()
|
|
{
|
|
//tutaj zamien bufory ze soba
|
|
var temp = vegetation;
|
|
vegetation = oldVegetation;
|
|
oldVegetation = temp;
|
|
|
|
computeShader.SetBuffer(0, "vegetation", vegetation);
|
|
computeShader.SetBuffer(0, "oldVegetation", oldVegetation);
|
|
}
|
|
void doSimulationSteps(int steps)
|
|
{
|
|
//tutaj wykonaj kroki symulacji
|
|
for (int i = 0; i < steps; i++)
|
|
{
|
|
computeShader.Dispatch(0, sizeX, sizeY, 1);
|
|
}
|
|
}
|
|
|
|
void recoverData()
|
|
{
|
|
//tutaj odczytaj bufor i przeslij wynik jako mapa detali
|
|
var result = new float[sizeX * sizeY];
|
|
vegetation.GetData(result);
|
|
int[,] detailLayer = new int[sizeX, sizeY];
|
|
|
|
for (int i = 0; i < sizeX; i++)
|
|
{
|
|
for (int j = 0; j < sizeX; j++)
|
|
{
|
|
detailLayer[i, j] = Mathf.FloorToInt(result[i + j * sizeX] * 10);
|
|
}
|
|
}
|
|
|
|
terrain.terrainData.SetDetailLayer(0, 0, 1, detailLayer);
|
|
}
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (doUpdate())
|
|
{
|
|
terrain = gameObject.GetComponent<Terrain>();
|
|
initParameters();
|
|
doSimulationSteps(stepsNumber);
|
|
recoverData();
|
|
}
|
|
}
|
|
}
|