Modelowanie_Wirtualnych_Swi.../Assets/Scripts/TurtleLSystem.cs
2021-07-09 23:35:24 +02:00

181 lines
6.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using ConsoleLSystem;
using System;
abstract public 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();
}
}
}