ZMWSLI0-SL2021-GR11/Projekt/MWSProjekt/Assets/Scripts/TurtleLSystem.cs

205 lines
6.6 KiB
C#
Raw Normal View History

2021-07-06 22:14:00 +02:00
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public abstract class TurtleLSystem : MonoBehaviour
{
public float speed;
private float nextStep;
public string LSystemPath;
public uint steps;
public Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>> turtleInterpretation = new Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>>();
private List<GameObject> gameObjects = new List<GameObject>();
private bool isAnimationRunning = false;
private Mesh getCylinder(int quality, float width, float length)
{
Mesh mesh = new Mesh();
//mesh.triangles
var points = new List<Vector3>();
var normals = new List<Vector3>();
var indices = new List<int>();
for (float i = 0; i < quality; i++)
{
points.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
}
for (float i = 0; i < quality; i++)
{
points.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, length, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
}
//points.Add(new Vector3(0,0,0));
//points.Add(new Vector3(0, length, 0));
for (float i = 0; i < quality; i++)
{
normals.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
}
for (float i = 0; i < quality; i++)
{
normals.Add(new Vector3(Mathf.Cos((i / quality) * 2 * Mathf.PI) * width, 0, Mathf.Sin((i / quality) * 2 * Mathf.PI) * width));
}
//for (int i = 0; i < quality; i++) {
// indices.Add(i);
// indices.Add((i + 1) % quality);
// indices.Add(quality * 2);
//}
//for (int i = 0; i < quality; i++) {
// indices.Add((i + 1) % quality + quality);
// indices.Add(i + quality);
// indices.Add(quality * 2 + 1);
//}
for (int i = 0; i < quality; i++)
{
indices.Add((i + 1) % quality);
indices.Add(i);
indices.Add(i + quality);
indices.Add(i + quality);
indices.Add((i + 1) % quality + quality);
indices.Add((i + 1) % quality);
}
mesh.vertices = points.ToArray();
mesh.triangles = indices.ToArray();
mesh.normals = normals.ToArray();
return mesh;
}
protected LSystemEvaluator evaluator = null;
private void parseRules(StreamReader sr)
{
}
public void evaluate()
{
for (int i = 0; i < steps; i++)
{
evaluator.rewrite();
}
Debug.Log(evaluator.lSystemString.ToString());
}
protected GameObject prepeareGameObject(string name, GameObject gameObject, Matrix4x4 transformation)
{
GameObject instance;
if (PrefabUtility.GetPrefabAssetType(gameObject) != PrefabAssetType.NotAPrefab)
{
instance = Instantiate(gameObject);
}
else
{
instance = gameObject;
}
instance.name = String.Format("LSystem Literal {0}", name);
instance.tag = "LSystemLiteral";
instance.transform.parent = this.gameObject.transform;
instance.transform.position = transformation.ExtractPosition() + transformation.MultiplyPoint(instance.transform.position);
instance.transform.rotation *= transformation.ExtractRotation();
instance.transform.localScale = Vector3.Scale(transformation.ExtractScale(), instance.transform.localScale);
return instance;
}
public void createModelsRecursive(LSystemNode node, Matrix4x4 transformation)
{
while (node != null)
{
Matrix4x4 new_transformation = transformation;
Func<float[], Tuple<GameObject, Matrix4x4>> interpretation;
var name = node.literal.name;
if (turtleInterpretation.TryGetValue(name, out interpretation) || turtleInterpretation.TryGetValue("*.*", out interpretation))
{
var result = interpretation(node.literal.values);
new_transformation = new_transformation * result.Item2;
if (result.Item1 != null)
{
var instance = prepeareGameObject(name, result.Item1, new_transformation);
}
//gameObjects.Add(gameObject);
//remove scale, rather unnecesary
new_transformation = new_transformation * Matrix4x4.Scale(result.Item2.ExtractScale()).inverse;
}
foreach (var child in node.children)
{
createModelsRecursive(child, new_transformation);
}
node = node.mainChild;
transformation = new_transformation;
}
}
private void clearObjects()
{
//var objects = Resources.FindObjectsOfTypeAll<GameObject>().Where(obj => obj.name == "Name");
foreach (GameObject gameObject in GameObject.FindGameObjectsWithTag("LSystemLiteral"))
{
DestroyImmediate(gameObject);
}
Debug.Log("#OldClear");
gameObjects = new List<GameObject>();
}
public void present()
{
clearObjects();
createModelsRecursive(evaluator.lSystemString, Matrix4x4.identity);
}
abstract protected void initLiteralInterpretation();
public void loadFile()
{
nextStep = Time.time;
clearObjects();
var sr = new StreamReader(LSystemPath);
evaluator = LSystemFileParser.parseLSystem(sr);
sr.Close();
turtleInterpretation = new Dictionary<string, Func<float[], Tuple<GameObject, Matrix4x4>>>();
initLiteralInterpretation();
}
public void evaluateAndPresent()
{
evaluate();
present();
Debug.Log(evaluator.lSystemString.ToString().Length);
//x.name = "aaa";
//Instantiate(x,Matrix4x4.identity);
}
public void switchAnimation()
{
this.isAnimationRunning = !this.isAnimationRunning;
nextStep = Time.time;
}
void runAnimation()
{
if (nextStep < Time.time)
{
for (int i = 0; i < (Time.time - nextStep) * speed; i++)
{
evaluator.rewrite();
}
present();
nextStep = Time.time + 1 / speed;
}
}
// Update is called once per frame
protected virtual void Update()
{
if (this.isAnimationRunning)
{
this.runAnimation();
}
}
}