ProjektMWS/Projekt MWS/Assets/Scripts/GrassController.cs
2021-07-06 19:43:27 +02:00

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