189 lines
4.9 KiB
C#
189 lines
4.9 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;
|
|
ComputeBuffer water;
|
|
ComputeBuffer oldWater;
|
|
|
|
ComputeBuffer feedModifier;
|
|
ComputeBuffer killModifier;
|
|
// Start is called before the first frame update
|
|
void Start() {
|
|
terrain = gameObject.GetComponent<Terrain>();
|
|
|
|
sizeX = terrain.terrainData.detailWidth;
|
|
sizeY = terrain.terrainData.detailWidth;
|
|
|
|
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);
|
|
|
|
initValues = new float[sizeX * sizeY];
|
|
|
|
for (int i = 0; i < sizeX * sizeY; i++)
|
|
{
|
|
initValues[i] = Random.Range(0.0f, 1.0f);
|
|
}
|
|
water.SetData(initValues);
|
|
oldWater.SetData(initValues);
|
|
}
|
|
|
|
public void resetGrass() {
|
|
initBufferValues();
|
|
|
|
terrain = gameObject.GetComponent<Terrain>();
|
|
|
|
sizeX = terrain.terrainData.detailWidth;
|
|
sizeY = terrain.terrainData.detailHeight;
|
|
|
|
|
|
var layer = new int[sizeX, sizeY];
|
|
|
|
for(int i =0; i<sizeX; i++)
|
|
{
|
|
layer[i, i] = 16;
|
|
}
|
|
terrain.terrainData.SetDetailLayer(0, 0, 1, layer);
|
|
|
|
}
|
|
void initParameters() {
|
|
//tutaj zainicjalizuj parametry
|
|
computeShader.SetInt("sizeX",sizeX);
|
|
computeShader.SetInt("sizeY", sizeY);
|
|
|
|
|
|
computeShader.SetFloat("DWater", DWater );
|
|
computeShader.SetFloat("DVegetation", DVegetation);
|
|
computeShader.SetFloat("feedRate", feedRate );
|
|
computeShader.SetFloat("killRate", killRate );
|
|
computeShader.SetFloat("dT", dT );
|
|
computeShader.SetFloat("stepsNumber", stepsNumber);
|
|
|
|
}
|
|
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);
|
|
computeShader.SetBuffer(0, "water", water);
|
|
computeShader.SetBuffer(0, "oldWater", oldWater);
|
|
|
|
|
|
initKillFeedBuffers();
|
|
initBufferValues();
|
|
initParameters();
|
|
}
|
|
|
|
|
|
void swapBuffers() {
|
|
//tutaj zamien bufory ze soba
|
|
|
|
var temp = vegetation;
|
|
vegetation = oldVegetation;
|
|
oldVegetation = temp;
|
|
|
|
temp = water;
|
|
water = oldWater;
|
|
oldWater = water;
|
|
|
|
computeShader.SetBuffer(0, "vegetation", vegetation);
|
|
computeShader.SetBuffer(0, "oldVegetation", oldVegetation);
|
|
|
|
computeShader.SetBuffer(0, "water", water);
|
|
computeShader.SetBuffer(0, "oldWater", oldWater);
|
|
}
|
|
void doSimulationSteps(int steps) {
|
|
//tutaj wykonaj kroki symulacji
|
|
for (int i = 0; i < steps; i++)
|
|
{
|
|
swapBuffers();
|
|
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);
|
|
|
|
var detailLayer = new int[sizeX, sizeY];
|
|
for (int i = 0; i < sizeX; i++)
|
|
for (int j = 0; j < sizeY; 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()) {
|
|
initParameters();
|
|
doSimulationSteps(stepsNumber);
|
|
recoverData();
|
|
}
|
|
}
|
|
}
|